Merge pull request #276 from Ella-0/master
[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                         // initializer is always created if value isn't null.
284                         createInitializer = value;
285                         break;
286
287                 default:
288                         createInitializer = false;
289                         break;
290         }
291
292         if (createInitializer)
293         {
294                 ExpressionGenerator generator(state);
295
296                 // Take copy of value range for generating initializer expression
297                 ValueRange valueRange = value->getValueRange();
298
299                 // Declare (removes value entry)
300                 state.getVariableManager().declareVariable(variable);
301
302                 bool isConst = m_variable->getStorage() == Variable::STORAGE_CONST;
303
304                 if (isConst)
305                         state.pushExpressionFlags(state.getExpressionFlags() | CONST_EXPR);
306
307                 m_expression = generator.generate(valueRange, 1);
308
309                 if (isConst)
310                         state.popExpressionFlags();
311         }
312         else
313                 state.getVariableManager().declareVariable(variable);
314 }
315
316 DeclarationStatement::~DeclarationStatement (void)
317 {
318         delete m_expression;
319 }
320
321 float DeclarationStatement::getWeight (const GeneratorState& state)
322 {
323         if (!hasDeclarableVars(state.getVariableManager()))
324                 return 0.0f;
325
326         if (!isCurrentTopStatementBlock(state))
327                 return 0.0f;
328
329         return state.getProgramParameters().declarationStatementBaseWeight;
330 }
331
332 void DeclarationStatement::tokenize (GeneratorState& state, TokenStream& str) const
333 {
334         m_variable->tokenizeDeclaration(state, str);
335
336         if (m_expression)
337         {
338                 str << Token::EQUAL;
339                 m_expression->tokenize(state, str);
340         }
341
342         str << Token::SEMICOLON << Token::NEWLINE;
343 }
344
345 void DeclarationStatement::execute (ExecutionContext& execCtx) const
346 {
347         if (m_expression)
348         {
349                 m_expression->evaluate(execCtx);
350                 execCtx.getValue(m_variable) = m_expression->getValue().value();
351         }
352 }
353
354 ConditionalStatement::ConditionalStatement (GeneratorState&)
355         : m_condition           (DE_NULL)
356         , m_trueStatement       (DE_NULL)
357         , m_falseStatement      (DE_NULL)
358 {
359 }
360
361 ConditionalStatement::~ConditionalStatement (void)
362 {
363         delete m_condition;
364         delete m_trueStatement;
365         delete m_falseStatement;
366 }
367
368 bool ConditionalStatement::isElseBlockRequired (const GeneratorState& state) const
369 {
370         // If parent is conditional statement with else block and this is the true statement,
371         // else block must be generated or otherwise parent "else" will end up parsed as else statement for this if.
372         const ConditionalStatement*     curChild        = this;
373         int                                                     curStackNdx     = state.getStatementDepth()-2;
374
375         while (curStackNdx >= 0)
376         {
377                 const ConditionalStatement* curParent = dynamic_cast<const ConditionalStatement*>(state.getStatementStackEntry(curStackNdx));
378
379                 if (!curParent)
380                         break; // Not a conditional statement - can end search here.
381
382                 if (curChild == curParent->m_trueStatement && curParent->m_falseStatement)
383                         return true; // Else block is mandatory.
384
385                 // Continue search.
386                 curChild         = curParent;
387                 curStackNdx     -= 1;
388         }
389
390         return false;
391 }
392
393 Statement* ConditionalStatement::createNextChild (GeneratorState& state)
394 {
395         // If has neither true or false statements, choose randomly whether to create false block.
396         if (!m_falseStatement && !m_trueStatement && (isElseBlockRequired(state) || state.getRandom().getBool()))
397         {
398                 // Construct false statement
399                 state.getVariableManager().pushValueScope(m_conditionalScope);
400                 m_falseStatement = createStatement(state);
401
402                 return m_falseStatement;
403         }
404         else if (!m_trueStatement)
405         {
406                 if (m_falseStatement)
407                 {
408                         // Pop previous value scope.
409                         state.getVariableManager().popValueScope();
410                         m_conditionalScope.clear();
411                 }
412
413                 // Construct true statement
414                 state.getVariableManager().pushValueScope(m_conditionalScope);
415                 m_trueStatement = createStatement(state);
416
417                 return m_trueStatement;
418         }
419         else
420         {
421                 // Pop conditional scope.
422                 state.getVariableManager().popValueScope();
423                 m_conditionalScope.clear();
424
425                 // Create condition
426                 DE_ASSERT(!m_condition);
427
428                 ExpressionGenerator generator(state);
429
430                 ValueRange range = ValueRange(VariableType::getScalarType(VariableType::TYPE_BOOL));
431                 range.getMin().asBool() = false;
432                 range.getMax().asBool() = true;
433
434                 m_condition = generator.generate(range, 1);
435
436                 return DE_NULL; // Done with this statement
437         }
438 }
439
440 namespace
441 {
442
443 bool isBlockStatement (const Statement* statement)
444 {
445         return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
446 }
447
448 bool isConditionalStatement (const Statement* statement)
449 {
450         return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
451 }
452
453 } // anonymous
454
455 void ConditionalStatement::tokenize (GeneratorState& state, TokenStream& str) const
456 {
457         DE_ASSERT(m_condition && m_trueStatement);
458
459         // if (condition)
460         str << Token::IF << Token::LEFT_PAREN;
461         m_condition->tokenize(state, str);
462         str << Token::RIGHT_PAREN << Token::NEWLINE;
463
464         // Statement executed if true
465         if (!isBlockStatement(m_trueStatement))
466         {
467                 str << Token::INDENT_INC;
468                 m_trueStatement->tokenize(state, str);
469                 str << Token::INDENT_DEC;
470         }
471         else
472                 m_trueStatement->tokenize(state, str);
473
474         if (m_falseStatement)
475         {
476                 str << Token::ELSE;
477
478                 if (isConditionalStatement(m_falseStatement))
479                 {
480                         m_falseStatement->tokenize(state, str);
481                 }
482                 else if (isBlockStatement(m_falseStatement))
483                 {
484                         str << Token::NEWLINE;
485                         m_falseStatement->tokenize(state, str);
486                 }
487                 else
488                 {
489                         str << Token::NEWLINE << Token::INDENT_INC;
490                         m_falseStatement->tokenize(state, str);
491                         str << Token::INDENT_DEC;
492                 }
493         }
494 }
495
496 void ConditionalStatement::execute (ExecutionContext& execCtx) const
497 {
498         // Evaluate condition
499         m_condition->evaluate(execCtx);
500
501         ExecMaskStorage maskStorage; // Value might change when we are evaluating true block so we have to take a copy.
502         ExecValueAccess trueMask        = maskStorage.getValue();
503
504         trueMask = m_condition->getValue().value();
505
506         // And mask, execute true statement and pop
507         execCtx.andExecutionMask(trueMask);
508         m_trueStatement->execute(execCtx);
509         execCtx.popExecutionMask();
510
511         if (m_falseStatement)
512         {
513                 // Construct negated mask, execute false statement and pop
514                 ExecMaskStorage tmp;
515                 ExecValueAccess falseMask = tmp.getValue();
516
517                 for (int i = 0; i < EXEC_VEC_WIDTH; i++)
518                         falseMask.asBool(i) = !trueMask.asBool(i);
519
520                 execCtx.andExecutionMask(falseMask);
521                 m_falseStatement->execute(execCtx);
522                 execCtx.popExecutionMask();
523         }
524 }
525
526 float ConditionalStatement::getWeight (const GeneratorState& state)
527 {
528         if (!state.getProgramParameters().useConditionals)
529                 return 0.0f;
530
531         int availableLevels = state.getShaderParameters().maxStatementDepth - state.getStatementDepth();
532         return (availableLevels > 1) ? 1.0f : 0.0f;
533 }
534
535 AssignStatement::AssignStatement (const Variable* variable, Expression* value)
536         : m_variable    (variable)
537         , m_valueExpr   (value) // \note Takes ownership of value
538 {
539 }
540
541 AssignStatement::AssignStatement (GeneratorState& state, const Variable* variable, ConstValueRangeAccess valueRange)
542         : m_variable    (variable)
543         , m_valueExpr   (DE_NULL)
544 {
545         // Generate random value
546         ExpressionGenerator generator(state);
547         m_valueExpr = generator.generate(valueRange, 1);
548 }
549
550 AssignStatement::~AssignStatement (void)
551 {
552         delete m_valueExpr;
553 }
554
555 void AssignStatement::tokenize (GeneratorState& state, TokenStream& str) const
556 {
557         str << Token(m_variable->getName()) << Token::EQUAL;
558         m_valueExpr->tokenize(state, str);
559         str << Token::SEMICOLON << Token::NEWLINE;
560 }
561
562 void AssignStatement::execute (ExecutionContext& execCtx) const
563 {
564         m_valueExpr->evaluate(execCtx);
565         assignMasked(execCtx.getValue(m_variable), m_valueExpr->getValue(), execCtx.getExecutionMask());
566 }
567
568 } // rsg