1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Random Shader Generator
3 * ----------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 *//*--------------------------------------------------------------------*/
24 #include "rsgBinaryOps.hpp"
25 #include "rsgVariableManager.hpp"
26 #include "rsgUtils.hpp"
34 template <int Precedence, Associativity Assoc>
35 BinaryOp<Precedence, Assoc>::BinaryOp (Token::Type operatorToken)
36 : m_operator (operatorToken)
37 , m_leftValueRange (m_type)
38 , m_rightValueRange (m_type)
39 , m_leftValueExpr (DE_NULL)
40 , m_rightValueExpr (DE_NULL)
44 template <int Precedence, Associativity Assoc>
45 BinaryOp<Precedence, Assoc>::~BinaryOp (void)
47 delete m_leftValueExpr;
48 delete m_rightValueExpr;
51 template <int Precedence, Associativity Assoc>
52 Expression* BinaryOp<Precedence, Assoc>::createNextChild (GeneratorState& state)
54 int leftPrec = Assoc == ASSOCIATIVITY_LEFT ? Precedence : Precedence-1;
55 int rightPrec = Assoc == ASSOCIATIVITY_LEFT ? Precedence-1 : Precedence;
57 if (m_rightValueExpr == DE_NULL)
59 state.pushPrecedence(rightPrec);
60 m_rightValueExpr = Expression::createRandom(state, m_rightValueRange.asAccess());
61 state.popPrecedence();
62 return m_rightValueExpr;
64 else if (m_leftValueExpr == DE_NULL)
66 state.pushPrecedence(leftPrec);
67 m_leftValueExpr = Expression::createRandom(state, m_leftValueRange.asAccess());
68 state.popPrecedence();
69 return m_leftValueExpr;
75 template <int Precedence, Associativity Assoc>
76 float BinaryOp<Precedence, Assoc>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
78 if (state.getPrecedence() < Precedence)
81 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
83 if (valueRange.getType().isVoid())
84 return availableLevels >= 2 ? unusedValueWeight : 0.0f;
86 if (availableLevels < getConservativeValueExprDepth(state, valueRange) + 1)
92 template <int Precedence, Associativity Assoc>
93 void BinaryOp<Precedence, Assoc>::tokenize (GeneratorState& state, TokenStream& str) const
95 m_leftValueExpr->tokenize(state, str);
97 m_rightValueExpr->tokenize(state, str);
100 template <int Precedence, Associativity Assoc>
101 void BinaryOp<Precedence, Assoc>::evaluate (ExecutionContext& execCtx)
103 m_leftValueExpr->evaluate(execCtx);
104 m_rightValueExpr->evaluate(execCtx);
106 ExecConstValueAccess leftVal = m_leftValueExpr->getValue();
107 ExecConstValueAccess rightVal = m_rightValueExpr->getValue();
108 ExecValueAccess dst = m_value.getValue(m_type);
110 evaluate(dst, leftVal, rightVal);
113 template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp>
114 BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::BinaryVecOp (GeneratorState& state, Token::Type operatorToken, ConstValueRangeAccess inValueRange)
115 : BinaryOp<Precedence, ASSOCIATIVITY_LEFT>(operatorToken)
117 ValueRange valueRange = inValueRange;
119 if (valueRange.getType().isVoid())
121 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
122 vector<VariableType::Type> baseTypes;
124 if (Float) baseTypes.push_back(VariableType::TYPE_FLOAT);
125 if (Int) baseTypes.push_back(VariableType::TYPE_INT);
126 if (Bool) baseTypes.push_back(VariableType::TYPE_BOOL);
128 VariableType::Type baseType = state.getRandom().choose<VariableType::Type>(baseTypes.begin(), baseTypes.end());
129 int numElements = state.getRandom().getInt(1, availableLevels >= 3 ? 4 : 1);
131 valueRange = ValueRange(VariableType(baseType, numElements));
132 computeRandomValueRange(state, valueRange.asAccess());
135 // Choose type, allocate storage for execution
136 this->m_type = valueRange.getType();
137 this->m_value.setStorage(this->m_type);
139 // Initialize storage for value ranges
140 this->m_rightValueRange = ValueRange(this->m_type);
141 this->m_leftValueRange = ValueRange(this->m_type);
143 VariableType::Type baseType = this->m_type.getBaseType();
145 // Compute range for b that satisfies requested value range
146 for (int elemNdx = 0; elemNdx < this->m_type.getNumElements(); elemNdx++)
148 ConstValueRangeAccess dst = valueRange.asAccess().component(elemNdx);
149 ValueRangeAccess a = this->m_leftValueRange.asAccess().component(elemNdx); // \todo [2011-03-25 pyry] Commutative: randomize inputs
150 ValueRangeAccess b = this->m_rightValueRange.asAccess().component(elemNdx);
152 // Just pass undefined ranges
153 if ((baseType == VariableType::TYPE_FLOAT || baseType == VariableType::TYPE_INT) && isUndefinedValueRange(dst))
155 a.getMin() = dst.getMin().value();
156 b.getMin() = dst.getMin().value();
157 a.getMax() = dst.getMax().value();
158 b.getMax() = dst.getMax().value();
162 if (baseType == VariableType::TYPE_FLOAT)
163 ComputeValueRange()(state.getRandom(), dst.getMin().asFloat(), dst.getMax().asFloat(),
164 a.getMin().asFloat(), a.getMax().asFloat(),
165 b.getMin().asFloat(), b.getMax().asFloat());
166 else if (baseType == VariableType::TYPE_INT)
167 ComputeValueRange()(state.getRandom(), dst.getMin().asInt(), dst.getMax().asInt(),
168 a.getMin().asInt(), a.getMax().asInt(),
169 b.getMin().asInt(), b.getMax().asInt());
172 DE_ASSERT(baseType == VariableType::TYPE_BOOL);
173 ComputeValueRange()(state.getRandom(), dst.getMin().asBool(), dst.getMax().asBool(),
174 a.getMin().asBool(), a.getMax().asBool(),
175 b.getMin().asBool(), b.getMax().asBool());
180 template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp>
181 BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::~BinaryVecOp (void)
185 template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp>
186 void BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
188 DE_ASSERT(dst.getType() == a.getType());
189 DE_ASSERT(dst.getType() == b.getType());
190 switch (dst.getType().getBaseType())
192 case VariableType::TYPE_FLOAT:
193 for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
195 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
196 dst.component(elemNdx).asFloat(compNdx) = EvaluateComp()(a.component(elemNdx).asFloat(compNdx), b.component(elemNdx).asFloat(compNdx));
200 case VariableType::TYPE_INT:
201 for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++)
203 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
204 dst.component(elemNdx).asInt(compNdx) = EvaluateComp()(a.component(elemNdx).asInt(compNdx), b.component(elemNdx).asInt(compNdx));
209 DE_ASSERT(DE_FALSE); // Invalid type for multiplication
213 void ComputeMulRange::operator() (de::Random& rnd, float dstMin, float dstMax, float& aMin, float& aMax, float& bMin, float& bMax) const
215 const float minScale = 0.25f;
216 const float maxScale = 2.0f;
217 const float subRangeStep = 0.25f;
218 const float scaleStep = 0.25f;
220 float scale = getQuantizedFloat(rnd, minScale, maxScale, scaleStep);
221 float scaledMin = dstMin/scale;
222 float scaledMax = dstMax/scale;
224 // Quantize scaled value range if possible
225 if (!quantizeFloatRange(scaledMin, scaledMax))
227 // Fall back to 1.0 as a scale
233 float subRangeLen = getQuantizedFloat(rnd, 0.0f, scaledMax-scaledMin, subRangeStep);
234 aMin = scaledMin + getQuantizedFloat(rnd, 0.0f, (scaledMax-scaledMin)-subRangeLen, subRangeStep);
235 aMax = aMin + subRangeLen;
240 for (int i = 0; i < 5; i++)
242 if (de::inBounds(aMin*(scale-(float)i*scaleStep), dstMin, dstMax) &&
243 de::inBounds(aMax*(scale-(float)i*scaleStep), dstMin, dstMax))
244 bMin = scale-(float)i*scaleStep;
246 if (de::inBounds(aMin*(scale+(float)i*scaleStep), dstMin, dstMax) &&
247 de::inBounds(aMax*(scale+(float)i*scaleStep), dstMin, dstMax))
248 bMax = scale+(float)i*scaleStep;
254 std::swap(aMin, aMax);
255 std::swap(bMin, bMax);
262 #if defined(DE_DEBUG)
263 const float eps = 0.001f;
264 DE_ASSERT(aMin <= aMax && bMin <= bMax);
265 DE_ASSERT(de::inRange(aMin*bMin, dstMin-eps, dstMax+eps));
266 DE_ASSERT(de::inRange(aMin*bMax, dstMin-eps, dstMax+eps));
267 DE_ASSERT(de::inRange(aMax*bMin, dstMin-eps, dstMax+eps));
268 DE_ASSERT(de::inRange(aMax*bMax, dstMin-eps, dstMax+eps));
272 void ComputeMulRange::operator() (de::Random& rnd, int dstMin, int dstMax, int& aMin, int& aMax, int& bMin, int& bMax) const
281 MulOp::MulOp (GeneratorState& state, ConstValueRangeAccess valueRange)
282 : MulBase(state, Token::MUL, valueRange)
286 float MulOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
288 if (valueRange.getType().isVoid() ||
289 valueRange.getType().isFloatOrVec() ||
290 valueRange.getType().isIntOrVec())
291 return MulBase::getWeight(state, valueRange);
296 template <typename T>
297 void ComputeAddRange::operator() (de::Random& random, T dstMin, T dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
301 int operator() (de::Random& rnd, int min, int max) const { return rnd.getInt(min, max); }
302 float operator() (de::Random& rnd, float min, float max) const { return getQuantizedFloat(rnd, min, max, 0.5f); }
305 T rangeLen = dstMax-dstMin;
306 T subRangeLen = GetRandom()(random, T(0), rangeLen);
307 T aOffset = GetRandom()(random, T(-8), T(8));
309 aMin = dstMin+aOffset;
310 aMax = aMin+subRangeLen;
313 bMax = -aOffset+(rangeLen-subRangeLen);
315 #if defined(DE_DEBUG)
317 DE_ASSERT(aMin <= aMax && bMin <= bMax);
318 DE_ASSERT(de::inRange(aMin+bMin, dstMin-eps, dstMax+eps));
319 DE_ASSERT(de::inRange(aMin+bMax, dstMin-eps, dstMax+eps));
320 DE_ASSERT(de::inRange(aMax+bMin, dstMin-eps, dstMax+eps));
321 DE_ASSERT(de::inRange(aMax+bMax, dstMin-eps, dstMax+eps));
326 void ComputeAddRange::operator()<bool> (de::Random&, bool, bool, bool&, bool&, bool&, bool&) const
331 AddOp::AddOp (GeneratorState& state, ConstValueRangeAccess valueRange)
332 : AddBase(state, Token::PLUS, valueRange)
336 float AddOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
338 if (valueRange.getType().isVoid() ||
339 valueRange.getType().isFloatOrVec() ||
340 valueRange.getType().isIntOrVec())
341 return AddBase::getWeight(state, valueRange);
346 template <typename T>
347 void ComputeSubRange::operator() (de::Random& random, T dstMin, T dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
351 int operator() (de::Random& rnd, int min, int max) const { return rnd.getInt(min, max); }
352 float operator() (de::Random& rnd, float min, float max) const { return getQuantizedFloat(rnd, min, max, 0.5f); }
355 T rangeLen = dstMax-dstMin;
356 T subRangeLen = GetRandom()(random, T(0), rangeLen);
357 T aOffset = GetRandom()(random, T(-8), T(8));
359 aMin = dstMin+aOffset;
360 aMax = aMin+subRangeLen;
362 bMin = aOffset-(rangeLen-subRangeLen);
365 #if defined(DE_DEBUG)
367 DE_ASSERT(aMin <= aMax && bMin <= bMax);
368 DE_ASSERT(de::inRange(aMin-bMin, dstMin-eps, dstMax+eps));
369 DE_ASSERT(de::inRange(aMin-bMax, dstMin-eps, dstMax+eps));
370 DE_ASSERT(de::inRange(aMax-bMin, dstMin-eps, dstMax+eps));
371 DE_ASSERT(de::inRange(aMax-bMax, dstMin-eps, dstMax+eps));
376 void ComputeSubRange::operator()<bool> (de::Random&, bool, bool, bool&, bool&, bool&, bool&) const
381 SubOp::SubOp (GeneratorState& state, ConstValueRangeAccess valueRange)
382 : SubBase(state, Token::MINUS, valueRange)
386 float SubOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
388 if (valueRange.getType().isVoid() ||
389 valueRange.getType().isFloatOrVec() ||
390 valueRange.getType().isIntOrVec())
391 return SubBase::getWeight(state, valueRange);
396 template <class ComputeValueRange, class EvaluateComp>
397 RelationalOp<ComputeValueRange, EvaluateComp>::RelationalOp (GeneratorState& state, Token::Type operatorToken, ConstValueRangeAccess inValueRange)
398 : BinaryOp<7, ASSOCIATIVITY_LEFT>(operatorToken)
400 ValueRange valueRange = inValueRange;
402 if (valueRange.getType().isVoid())
404 valueRange = ValueRange(VariableType(VariableType::TYPE_BOOL, 1));
405 computeRandomValueRange(state, valueRange.asAccess());
408 // Choose type, allocate storage for execution
409 this->m_type = valueRange.getType();
410 this->m_value.setStorage(this->m_type);
412 // Choose random input type
413 VariableType::Type inBaseTypes[] = { VariableType::TYPE_FLOAT, VariableType::TYPE_INT };
414 VariableType::Type inBaseType = state.getRandom().choose<VariableType::Type>(&inBaseTypes[0], &inBaseTypes[DE_LENGTH_OF_ARRAY(inBaseTypes)]);
416 // Initialize storage for input value ranges
417 this->m_rightValueRange = ValueRange(VariableType(inBaseType, 1));
418 this->m_leftValueRange = ValueRange(VariableType(inBaseType, 1));
420 // Compute range for b that satisfies requested value range
422 bool dstMin = valueRange.getMin().asBool();
423 bool dstMax = valueRange.getMax().asBool();
424 ValueRangeAccess a = this->m_leftValueRange.asAccess();
425 ValueRangeAccess b = this->m_rightValueRange.asAccess();
427 if (inBaseType == VariableType::TYPE_FLOAT)
428 ComputeValueRange()(state.getRandom(), dstMin, dstMax,
429 a.getMin().asFloat(), a.getMax().asFloat(),
430 b.getMin().asFloat(), b.getMax().asFloat());
431 else if (inBaseType == VariableType::TYPE_INT)
432 ComputeValueRange()(state.getRandom(), dstMin, dstMax,
433 a.getMin().asInt(), a.getMax().asInt(),
434 b.getMin().asInt(), b.getMax().asInt());
438 template <class ComputeValueRange, class EvaluateComp>
439 RelationalOp<ComputeValueRange, EvaluateComp>::~RelationalOp (void)
443 template <class ComputeValueRange, class EvaluateComp>
444 void RelationalOp<ComputeValueRange, EvaluateComp>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
446 DE_ASSERT(a.getType() == b.getType());
447 switch (a.getType().getBaseType())
449 case VariableType::TYPE_FLOAT:
450 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
451 dst.asBool(compNdx) = EvaluateComp()(a.asFloat(compNdx), b.asFloat(compNdx));
454 case VariableType::TYPE_INT:
455 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
456 dst.asBool(compNdx) = EvaluateComp()(a.asInt(compNdx), b.asInt(compNdx));
464 template <class ComputeValueRange, class EvaluateComp>
465 float RelationalOp<ComputeValueRange, EvaluateComp>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
467 if (!state.getProgramParameters().useComparisonOps)
470 if (valueRange.getType().isVoid() ||
471 (valueRange.getType().getBaseType() == VariableType::TYPE_BOOL && valueRange.getType().getNumElements() == 1))
472 return BinaryOp<7, ASSOCIATIVITY_LEFT>::getWeight(state, valueRange);
480 template <typename T> T getStep (void);
481 template <> inline float getStep (void) { return 0.25f; }
482 template <> inline int getStep (void) { return 1; }
486 template <typename T>
487 void ComputeLessThanRange::operator () (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
491 int operator() (de::Random& random, int min, int max) const { return random.getInt(min, max); }
492 float operator() (de::Random& random, float min, float max) const { return getQuantizedFloat(random, min, max, getStep<float>()); }
496 T rLen = GetRandom()(rnd, T(0), T(8));
497 T rMin = GetRandom()(rnd, T(-4), T(4));
500 if (dstMin == false && dstMax == true)
502 // Both values are possible, use same range for both inputs
508 else if (dstMin == true && dstMax == true)
510 // Compute range that is less than rMin..rMax
511 T aLen = GetRandom()(rnd, T(0), T(8)-rLen);
513 aMax = rMin - getStep<T>();
521 // Compute range that is greater than or equal to rMin..rMax
522 T aLen = GetRandom()(rnd, T(0), T(8)-rLen);
532 LessThanOp::LessThanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
533 : LessThanBase(state, Token::CMP_LT, valueRange)
537 float LessThanOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
539 return LessThanBase::getWeight(state, valueRange);
542 template <typename T>
543 void ComputeLessOrEqualRange::operator () (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const
547 int operator() (de::Random& random, int min, int max) const { return random.getInt(min, max); }
548 float operator() (de::Random& random, float min, float max) const { return getQuantizedFloat(random, min, max, getStep<float>()); }
552 T rLen = GetRandom()(rnd, T(0), T(8));
553 T rMin = GetRandom()(rnd, T(-4), T(4));
556 if (dstMin == false && dstMax == true)
558 // Both values are possible, use same range for both inputs
564 else if (dstMin == true && dstMax == true)
566 // Compute range that is less than or equal to rMin..rMax
567 T aLen = GetRandom()(rnd, T(0), T(8)-rLen);
577 // Compute range that is greater than rMin..rMax
578 T aLen = GetRandom()(rnd, T(0), T(8)-rLen);
580 aMin = rMax + getStep<T>();
588 LessOrEqualOp::LessOrEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
589 : LessOrEqualBase(state, Token::CMP_LE, valueRange)
593 float LessOrEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
595 return LessOrEqualBase::getWeight(state, valueRange);
598 GreaterThanOp::GreaterThanOp (GeneratorState& state, ConstValueRangeAccess valueRange)
599 : GreaterThanBase(state, Token::CMP_GT, valueRange)
603 float GreaterThanOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
605 return GreaterThanBase::getWeight(state, valueRange);
608 GreaterOrEqualOp::GreaterOrEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
609 : GreaterOrEqualBase(state, Token::CMP_GE, valueRange)
613 float GreaterOrEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
615 return GreaterOrEqualBase::getWeight(state, valueRange);
621 template <bool IsEqual, typename T>
622 void computeEqualityValueRange (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax)
624 if (dstMin == false && dstMax == true)
625 ComputeLessThanRange()(rnd, false, true, aMin, aMax, bMin, bMax);
626 else if (IsEqual && dstMin == false)
627 ComputeLessThanRange()(rnd, true, true, aMin, aMax, bMin, bMax);
628 else if (!IsEqual && dstMin == true)
629 ComputeLessThanRange()(rnd, true, true, aMin, aMax, bMin, bMax);
632 // Must have exactly same values.
635 int operator() (de::Random& random, int min, int max) const { return random.getInt(min, max); }
636 float operator() (de::Random& random, float min, float max) const { return getQuantizedFloat(random, min, max, 0.5f); }
639 T val = GetRandom()(rnd, T(-1), T(1));
649 void computeEqualityValueRange<true, bool> (de::Random& rnd, bool dstMin, bool dstMax, bool& aMin, bool& aMax, bool& bMin, bool& bMax)
651 if (dstMin == false && dstMax == true)
658 else if (dstMin == false)
660 DE_ASSERT(dstMax == false);
661 bool val = rnd.getBool();
670 DE_ASSERT(dstMin == true && dstMax == true);
671 bool val = rnd.getBool();
681 void computeEqualityValueRange<false, bool> (de::Random& rnd, bool dstMin, bool dstMax, bool& aMin, bool& aMax, bool& bMin, bool& bMax)
683 if (dstMin == false && dstMax == true)
684 computeEqualityValueRange<true>(rnd, dstMin, dstMax, aMin, aMax, bMin, bMax);
686 computeEqualityValueRange<true>(rnd, !dstMin, !dstMax, aMin, aMax, bMin, bMax);
691 template <bool IsEqual>
692 EqualityComparisonOp<IsEqual>::EqualityComparisonOp (GeneratorState& state, ConstValueRangeAccess inValueRange)
693 : BinaryOp<8, ASSOCIATIVITY_LEFT>(IsEqual ? Token::CMP_EQ : Token::CMP_NE)
695 ValueRange valueRange = inValueRange;
697 if (valueRange.getType().isVoid())
699 valueRange = ValueRange(VariableType(VariableType::TYPE_BOOL, 1));
700 computeRandomValueRange(state, valueRange.asAccess());
703 // Choose type, allocate storage for execution
704 this->m_type = valueRange.getType();
705 this->m_value.setStorage(this->m_type);
707 // Choose random input type
708 VariableType::Type inBaseTypes[] = { VariableType::TYPE_FLOAT, VariableType::TYPE_INT };
709 VariableType::Type inBaseType = state.getRandom().choose<VariableType::Type>(&inBaseTypes[0], &inBaseTypes[DE_LENGTH_OF_ARRAY(inBaseTypes)]);
710 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();
711 int numElements = state.getRandom().getInt(1, availableLevels >= 3 ? 4 : 1);
713 // Initialize storage for input value ranges
714 this->m_rightValueRange = ValueRange(VariableType(inBaseType, numElements));
715 this->m_leftValueRange = ValueRange(VariableType(inBaseType, numElements));
717 // Compute range for b that satisfies requested value range
718 for (int elementNdx = 0; elementNdx < numElements; elementNdx++)
720 bool dstMin = valueRange.getMin().asBool();
721 bool dstMax = valueRange.getMax().asBool();
723 ValueRangeAccess a = this->m_leftValueRange.asAccess().component(elementNdx);
724 ValueRangeAccess b = this->m_rightValueRange.asAccess().component(elementNdx);
726 if (inBaseType == VariableType::TYPE_FLOAT)
727 computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax,
728 a.getMin().asFloat(), a.getMax().asFloat(),
729 b.getMin().asFloat(), b.getMax().asFloat());
730 else if (inBaseType == VariableType::TYPE_INT)
731 computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax,
732 a.getMin().asInt(), a.getMax().asInt(),
733 b.getMin().asInt(), b.getMax().asInt());
736 DE_ASSERT(inBaseType == VariableType::TYPE_BOOL);
737 computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax,
738 a.getMin().asBool(), a.getMax().asBool(),
739 b.getMin().asBool(), b.getMax().asBool());
744 template <bool IsEqual>
745 float EqualityComparisonOp<IsEqual>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
747 if (!state.getProgramParameters().useComparisonOps)
750 // \todo [2011-06-13 pyry] Weight down cases that would force constant inputs.
752 if (valueRange.getType().isVoid() ||
753 (valueRange.getType().getBaseType() == VariableType::TYPE_BOOL && valueRange.getType().getNumElements() == 1))
754 return BinaryOp<8, ASSOCIATIVITY_LEFT>::getWeight(state, valueRange);
762 template <bool IsEqual>
763 struct EqualityCompare
765 template <typename T>
766 static bool compare (T a, T b);
767 static bool combine (bool a, bool b);
771 template <typename T>
772 inline bool EqualityCompare<true>::compare (T a, T b) { return a == b; }
775 inline bool EqualityCompare<true>::combine (bool a, bool b) { return a && b; }
778 template <typename T>
779 inline bool EqualityCompare<false>::compare (T a, T b) { return a != b; }
782 inline bool EqualityCompare<false>::combine (bool a, bool b) { return a || b; }
786 template <bool IsEqual>
787 void EqualityComparisonOp<IsEqual>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b)
789 DE_ASSERT(a.getType() == b.getType());
792 switch (a.getType().getBaseType())
794 case VariableType::TYPE_FLOAT:
795 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
797 bool result = IsEqual ? true : false;
799 for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++)
800 result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asFloat(compNdx), b.component(elemNdx).asFloat(compNdx)));
802 dst.asBool(compNdx) = result;
806 case VariableType::TYPE_INT:
807 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
809 bool result = IsEqual ? true : false;
811 for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++)
812 result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asInt(compNdx), b.component(elemNdx).asInt(compNdx)));
814 dst.asBool(compNdx) = result;
818 case VariableType::TYPE_BOOL:
819 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++)
821 bool result = IsEqual ? true : false;
823 for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++)
824 result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asBool(compNdx), b.component(elemNdx).asBool(compNdx)));
826 dst.asBool(compNdx) = result;
835 EqualOp::EqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
836 : EqualityComparisonOp<true>(state, valueRange)
840 float EqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
842 return EqualityComparisonOp<true>::getWeight(state, valueRange);
845 NotEqualOp::NotEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange)
846 : EqualityComparisonOp<false>(state, valueRange)
850 float NotEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
852 return EqualityComparisonOp<false>::getWeight(state, valueRange);