Test behaviour of color write enable with colorWriteMask
[platform/upstream/VK-GL-CTS.git] / framework / randomshaders / rsgStatement.cpp
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 Statements.
22  *//*--------------------------------------------------------------------*/
23
24 #include "rsgStatement.hpp"
25 #include "rsgExpressionGenerator.hpp"
26 #include "rsgUtils.hpp"
27
28 #include <typeinfo>
29
30 using std::vector;
31
32 namespace rsg
33 {
34
35 namespace
36 {
37
38 inline bool isCurrentTopStatementBlock (const GeneratorState& state)
39 {
40         int stackDepth = state.getStatementDepth();
41         return dynamic_cast<const BlockStatement*>(state.getStatementStackEntry(stackDepth-1)) != DE_NULL;
42 }
43
44 template <class T> float                getWeight       (const GeneratorState& state)   { return T::getWeight(state);   }
45 template <class T> Statement*   create          (GeneratorState& state)                 { return new T(state);                  }
46
47 struct StatementSpec
48 {
49         float           (*getWeight)            (const GeneratorState& state);
50         Statement*      (*create)                       (GeneratorState& state);
51 };
52
53 const StatementSpec* chooseStatement (GeneratorState& state)
54 {
55         static const StatementSpec statementSpecs[] =
56         {
57                 { getWeight<BlockStatement>,            create<BlockStatement>                  },
58                 { getWeight<ExpressionStatement>,       create<ExpressionStatement>             },
59                 { getWeight<DeclarationStatement>,      create<DeclarationStatement>    },
60                 { getWeight<ConditionalStatement>,      create<ConditionalStatement>    }
61         };
62
63         float weights[DE_LENGTH_OF_ARRAY(statementSpecs)];
64
65         // Compute weights
66         float sum = 0.0f;
67         for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
68         {
69                 weights[ndx] = statementSpecs[ndx].getWeight(state);
70                 sum += weights[ndx];
71         }
72
73         DE_ASSERT(sum > 0.0f);
74
75         // Random number in range
76         float p = state.getRandom().getFloat(0.0f, sum);
77
78         const StatementSpec* spec                       = DE_NULL;
79         const StatementSpec* lastNonZero        = DE_NULL;
80
81         // Find element in that point
82         sum = 0.0f;
83         for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
84         {
85                 sum += weights[ndx];
86                 if (p < sum)
87                 {
88                         spec = &statementSpecs[ndx];
89                         break;
90                 }
91                 else if (weights[ndx] > 0.0f)
92                         lastNonZero = &statementSpecs[ndx];
93         }
94
95         if (!spec)
96                 spec = lastNonZero;
97
98         return spec;
99 }
100
101 Statement* createStatement (GeneratorState& state)
102 {
103         return chooseStatement(state)->create(state);
104 }
105
106 } // anonymous
107
108 Statement::Statement (void)
109 {
110 }
111
112 Statement::~Statement (void)
113 {
114 }
115
116 ExpressionStatement::ExpressionStatement (GeneratorState& state)
117         : m_expression(DE_NULL)
118 {
119         ExpressionGenerator generator(state);
120         m_expression = generator.generate(ValueRange(VariableType(VariableType::TYPE_VOID)));
121 }
122
123 ExpressionStatement::~ExpressionStatement (void)
124 {
125         delete m_expression;
126 }
127
128 float ExpressionStatement::getWeight (const GeneratorState& state)
129 {
130         DE_UNREF(state);
131         return 1.0f;
132 }
133
134 void ExpressionStatement::execute (ExecutionContext& execCtx) const
135 {
136         m_expression->evaluate(execCtx);
137 }
138
139 BlockStatement::BlockStatement (GeneratorState& state)
140 {
141         init(state);
142 }
143
144 void BlockStatement::init (GeneratorState& state)
145 {
146         // Select number of children statements to construct
147         m_numChildrenToCreate = state.getRandom().getInt(0, state.getShaderParameters().maxStatementsPerBlock);
148
149         // Push scope
150         state.getVariableManager().pushVariableScope(m_scope);
151 }
152
153 BlockStatement::~BlockStatement (void)
154 {
155         for (vector<Statement*>::iterator i = m_children.begin(); i != m_children.end(); i++)
156                 delete *i;
157         m_children.clear();
158 }
159
160 void BlockStatement::addChild (Statement* statement)
161 {
162         try
163         {
164                 m_children.push_back(statement);
165         }
166         catch (const std::exception&)
167         {
168                 delete statement;
169                 throw;
170         }
171 }
172
173 Statement* BlockStatement::createNextChild (GeneratorState& state)
174 {
175         if ((int)m_children.size() < m_numChildrenToCreate)
176         {
177                 // Select and create a new child
178                 Statement* child = createStatement(state);
179                 addChild(child);
180                 return child;
181         }
182         else
183         {
184                 // Done, pop scope
185                 state.getVariableManager().popVariableScope();
186                 return DE_NULL;
187         }
188 }
189
190 float BlockStatement::getWeight (const GeneratorState& state)
191 {
192         if (state.getStatementDepth()+1 < state.getShaderParameters().maxStatementDepth)
193         {
194                 if (isCurrentTopStatementBlock(state))
195                         return 0.2f; // Low probability for anonymous blocks.
196                 else
197                         return 1.0f;
198         }
199         else
200                 return 0.0f;
201 }
202
203 void BlockStatement::tokenize (GeneratorState& state, TokenStream& str) const
204 {
205         str << Token::LEFT_BRACE << Token::NEWLINE << Token::INDENT_INC;
206
207         for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
208                 (*i)->tokenize(state, str);
209
210         str << Token::INDENT_DEC << Token::RIGHT_BRACE << Token::NEWLINE;
211 }
212
213 void BlockStatement::execute (ExecutionContext& execCtx) const
214 {
215         for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
216                 (*i)->execute(execCtx);
217 }
218
219 void ExpressionStatement::tokenize (GeneratorState& state, TokenStream& str) const
220 {
221         DE_ASSERT(m_expression);
222         m_expression->tokenize(state, str);
223         str << Token::SEMICOLON << Token::NEWLINE;
224 }
225
226 namespace
227 {
228
229 inline bool canDeclareVariable (const Variable* variable)
230 {
231         return variable->getStorage() == Variable::STORAGE_LOCAL;
232 }
233
234 bool hasDeclarableVars (const VariableManager& varMgr)
235 {
236         const vector<Variable*>& liveVars = varMgr.getLiveVariables();
237         for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
238         {
239                 if (canDeclareVariable(*i))
240                         return true;
241         }
242         return false;
243 }
244
245 } // anonymous
246
247 DeclarationStatement::DeclarationStatement (GeneratorState& state, Variable* variable)
248         : m_variable    (DE_NULL)
249         , m_expression  (DE_NULL)
250 {
251         if (variable == DE_NULL)
252         {
253                 // Choose random
254                 // \todo [2011-02-03 pyry] Allocate a new here?
255                 // \todo [2011-05-26 pyry] Weights?
256                 const vector<Variable*>&        liveVars = state.getVariableManager().getLiveVariables();
257                 vector<Variable*>                       candidates;
258
259                 for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
260                 {
261                         if (canDeclareVariable(*i))
262                                 candidates.push_back(*i);
263                 }
264
265                 variable = state.getRandom().choose<Variable*>(candidates.begin(), candidates.end());
266         }
267
268         DE_ASSERT(variable);
269         m_variable = variable;
270
271         const ValueEntry* value = state.getVariableManager().getValue(variable);
272
273         bool createInitializer = false;
274
275         switch (m_variable->getStorage())
276         {
277                 case Variable::STORAGE_CONST:
278                         DE_ASSERT(value);
279                         createInitializer = true;
280                         break;
281
282                 case Variable::STORAGE_LOCAL:
283                         // \note Currently booleans are always treated as not having undefined range and thus
284                         //       initializer is always created.
285                         createInitializer = value && !isUndefinedValueRange(value->getValueRange());
286                         break;
287
288                 default:
289                         createInitializer = false;
290                         break;
291         }
292
293         if (createInitializer)
294         {
295                 ExpressionGenerator generator(state);
296
297                 // Take copy of value range for generating initializer expression
298                 ValueRange valueRange = value->getValueRange();
299
300                 // Declare (removes value entry)
301                 state.getVariableManager().declareVariable(variable);
302
303                 bool isConst = m_variable->getStorage() == Variable::STORAGE_CONST;
304
305                 if (isConst)
306                         state.pushExpressionFlags(state.getExpressionFlags() | CONST_EXPR);
307
308                 m_expression = generator.generate(valueRange, 1);
309
310                 if (isConst)
311                         state.popExpressionFlags();
312         }
313         else
314                 state.getVariableManager().declareVariable(variable);
315 }
316
317 DeclarationStatement::~DeclarationStatement (void)
318 {
319         delete m_expression;
320 }
321
322 float DeclarationStatement::getWeight (const GeneratorState& state)
323 {
324         if (!hasDeclarableVars(state.getVariableManager()))
325                 return 0.0f;
326
327         if (!isCurrentTopStatementBlock(state))
328                 return 0.0f;
329
330         return state.getProgramParameters().declarationStatementBaseWeight;
331 }
332
333 void DeclarationStatement::tokenize (GeneratorState& state, TokenStream& str) const
334 {
335         m_variable->tokenizeDeclaration(state, str);
336
337         if (m_expression)
338         {
339                 str << Token::EQUAL;
340                 m_expression->tokenize(state, str);
341         }
342
343         str << Token::SEMICOLON << Token::NEWLINE;
344 }
345
346 void DeclarationStatement::execute (ExecutionContext& execCtx) const
347 {
348         if (m_expression)
349         {
350                 m_expression->evaluate(execCtx);
351                 execCtx.getValue(m_variable) = m_expression->getValue().value();
352         }
353 }
354
355 ConditionalStatement::ConditionalStatement (GeneratorState&)
356         : m_condition           (DE_NULL)
357         , m_trueStatement       (DE_NULL)
358         , m_falseStatement      (DE_NULL)
359 {
360 }
361
362 ConditionalStatement::~ConditionalStatement (void)
363 {
364         delete m_condition;
365         delete m_trueStatement;
366         delete m_falseStatement;
367 }
368
369 bool ConditionalStatement::isElseBlockRequired (const GeneratorState& state) const
370 {
371         // If parent is conditional statement with else block and this is the true statement,
372         // else block must be generated or otherwise parent "else" will end up parsed as else statement for this if.
373         const ConditionalStatement*     curChild        = this;
374         int                                                     curStackNdx     = state.getStatementDepth()-2;
375
376         while (curStackNdx >= 0)
377         {
378                 const ConditionalStatement* curParent = dynamic_cast<const ConditionalStatement*>(state.getStatementStackEntry(curStackNdx));
379
380                 if (!curParent)
381                         break; // Not a conditional statement - can end search here.
382
383                 if (curChild == curParent->m_trueStatement && curParent->m_falseStatement)
384                         return true; // Else block is mandatory.
385
386                 // Continue search.
387                 curChild         = curParent;
388                 curStackNdx     -= 1;
389         }
390
391         return false;
392 }
393
394 Statement* ConditionalStatement::createNextChild (GeneratorState& state)
395 {
396         // If has neither true or false statements, choose randomly whether to create false block.
397         if (!m_falseStatement && !m_trueStatement && (isElseBlockRequired(state) || state.getRandom().getBool()))
398         {
399                 // Construct false statement
400                 state.getVariableManager().pushValueScope(m_conditionalScope);
401                 m_falseStatement = createStatement(state);
402
403                 return m_falseStatement;
404         }
405         else if (!m_trueStatement)
406         {
407                 if (m_falseStatement)
408                 {
409                         // Pop previous value scope.
410                         state.getVariableManager().popValueScope();
411                         m_conditionalScope.clear();
412                 }
413
414                 // Construct true statement
415                 state.getVariableManager().pushValueScope(m_conditionalScope);
416                 m_trueStatement = createStatement(state);
417
418                 return m_trueStatement;
419         }
420         else
421         {
422                 // Pop conditional scope.
423                 state.getVariableManager().popValueScope();
424                 m_conditionalScope.clear();
425
426                 // Create condition
427                 DE_ASSERT(!m_condition);
428
429                 ExpressionGenerator generator(state);
430
431                 ValueRange range = ValueRange(VariableType::getScalarType(VariableType::TYPE_BOOL));
432                 range.getMin().asBool() = false;
433                 range.getMax().asBool() = true;
434
435                 m_condition = generator.generate(range, 1);
436
437                 return DE_NULL; // Done with this statement
438         }
439 }
440
441 namespace
442 {
443
444 bool isBlockStatement (const Statement* statement)
445 {
446         return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
447 }
448
449 bool isConditionalStatement (const Statement* statement)
450 {
451         return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
452 }
453
454 } // anonymous
455
456 void ConditionalStatement::tokenize (GeneratorState& state, TokenStream& str) const
457 {
458         DE_ASSERT(m_condition && m_trueStatement);
459
460         // if (condition)
461         str << Token::IF << Token::LEFT_PAREN;
462         m_condition->tokenize(state, str);
463         str << Token::RIGHT_PAREN << Token::NEWLINE;
464
465         // Statement executed if true
466         if (!isBlockStatement(m_trueStatement))
467         {
468                 str << Token::INDENT_INC;
469                 m_trueStatement->tokenize(state, str);
470                 str << Token::INDENT_DEC;
471         }
472         else
473                 m_trueStatement->tokenize(state, str);
474
475         if (m_falseStatement)
476         {
477                 str << Token::ELSE;
478
479                 if (isConditionalStatement(m_falseStatement))
480                 {
481                         m_falseStatement->tokenize(state, str);
482                 }
483                 else if (isBlockStatement(m_falseStatement))
484                 {
485                         str << Token::NEWLINE;
486                         m_falseStatement->tokenize(state, str);
487                 }
488                 else
489                 {
490                         str << Token::NEWLINE << Token::INDENT_INC;
491                         m_falseStatement->tokenize(state, str);
492                         str << Token::INDENT_DEC;
493                 }
494         }
495 }
496
497 void ConditionalStatement::execute (ExecutionContext& execCtx) const
498 {
499         // Evaluate condition
500         m_condition->evaluate(execCtx);
501
502         ExecMaskStorage maskStorage; // Value might change when we are evaluating true block so we have to take a copy.
503         ExecValueAccess trueMask        = maskStorage.getValue();
504
505         trueMask = m_condition->getValue().value();
506
507         // And mask, execute true statement and pop
508         execCtx.andExecutionMask(trueMask);
509         m_trueStatement->execute(execCtx);
510         execCtx.popExecutionMask();
511
512         if (m_falseStatement)
513         {
514                 // Construct negated mask, execute false statement and pop
515                 ExecMaskStorage tmp;
516                 ExecValueAccess falseMask = tmp.getValue();
517
518                 for (int i = 0; i < EXEC_VEC_WIDTH; i++)
519                         falseMask.asBool(i) = !trueMask.asBool(i);
520
521                 execCtx.andExecutionMask(falseMask);
522                 m_falseStatement->execute(execCtx);
523                 execCtx.popExecutionMask();
524         }
525 }
526
527 float ConditionalStatement::getWeight (const GeneratorState& state)
528 {
529         if (!state.getProgramParameters().useConditionals)
530                 return 0.0f;
531
532         int availableLevels = state.getShaderParameters().maxStatementDepth - state.getStatementDepth();
533         return (availableLevels > 1) ? 1.0f : 0.0f;
534 }
535
536 AssignStatement::AssignStatement (const Variable* variable, Expression* value)
537         : m_variable    (variable)
538         , m_valueExpr   (value) // \note Takes ownership of value
539 {
540 }
541
542 AssignStatement::AssignStatement (GeneratorState& state, const Variable* variable, ConstValueRangeAccess valueRange)
543         : m_variable    (variable)
544         , m_valueExpr   (DE_NULL)
545 {
546         // Generate random value
547         ExpressionGenerator generator(state);
548         m_valueExpr = generator.generate(valueRange, 1);
549 }
550
551 AssignStatement::~AssignStatement (void)
552 {
553         delete m_valueExpr;
554 }
555
556 void AssignStatement::tokenize (GeneratorState& state, TokenStream& str) const
557 {
558         str << Token(m_variable->getName()) << Token::EQUAL;
559         m_valueExpr->tokenize(state, str);
560         str << Token::SEMICOLON << Token::NEWLINE;
561 }
562
563 void AssignStatement::execute (ExecutionContext& execCtx) const
564 {
565         m_valueExpr->evaluate(execCtx);
566         assignMasked(execCtx.getValue(m_variable), m_valueExpr->getValue(), execCtx.getExecutionMask());
567 }
568
569 } // rsg