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 "rsgStatement.hpp"
25 #include "rsgExpressionGenerator.hpp"
26 #include "rsgUtils.hpp"
38 inline bool isCurrentTopStatementBlock (const GeneratorState& state)
40 int stackDepth = state.getStatementDepth();
41 return dynamic_cast<const BlockStatement*>(state.getStatementStackEntry(stackDepth-1)) != DE_NULL;
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); }
49 float (*getWeight) (const GeneratorState& state);
50 Statement* (*create) (GeneratorState& state);
53 const StatementSpec* chooseStatement (GeneratorState& state)
55 static const StatementSpec statementSpecs[] =
57 { getWeight<BlockStatement>, create<BlockStatement> },
58 { getWeight<ExpressionStatement>, create<ExpressionStatement> },
59 { getWeight<DeclarationStatement>, create<DeclarationStatement> },
60 { getWeight<ConditionalStatement>, create<ConditionalStatement> }
63 float weights[DE_LENGTH_OF_ARRAY(statementSpecs)];
67 for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
69 weights[ndx] = statementSpecs[ndx].getWeight(state);
73 DE_ASSERT(sum > 0.0f);
75 // Random number in range
76 float p = state.getRandom().getFloat(0.0f, sum);
78 const StatementSpec* spec = DE_NULL;
79 const StatementSpec* lastNonZero = DE_NULL;
81 // Find element in that point
83 for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
88 spec = &statementSpecs[ndx];
91 else if (weights[ndx] > 0.0f)
92 lastNonZero = &statementSpecs[ndx];
101 Statement* createStatement (GeneratorState& state)
103 return chooseStatement(state)->create(state);
108 Statement::Statement (void)
112 Statement::~Statement (void)
116 ExpressionStatement::ExpressionStatement (GeneratorState& state)
117 : m_expression(DE_NULL)
119 ExpressionGenerator generator(state);
120 m_expression = generator.generate(ValueRange(VariableType(VariableType::TYPE_VOID)));
123 ExpressionStatement::~ExpressionStatement (void)
128 float ExpressionStatement::getWeight (const GeneratorState& state)
134 void ExpressionStatement::execute (ExecutionContext& execCtx) const
136 m_expression->evaluate(execCtx);
139 BlockStatement::BlockStatement (GeneratorState& state)
144 void BlockStatement::init (GeneratorState& state)
146 // Select number of children statements to construct
147 m_numChildrenToCreate = state.getRandom().getInt(0, state.getShaderParameters().maxStatementsPerBlock);
150 state.getVariableManager().pushVariableScope(m_scope);
153 BlockStatement::~BlockStatement (void)
155 for (vector<Statement*>::iterator i = m_children.begin(); i != m_children.end(); i++)
160 void BlockStatement::addChild (Statement* statement)
164 m_children.push_back(statement);
166 catch (const std::exception&)
173 Statement* BlockStatement::createNextChild (GeneratorState& state)
175 if ((int)m_children.size() < m_numChildrenToCreate)
177 // Select and create a new child
178 Statement* child = createStatement(state);
185 state.getVariableManager().popVariableScope();
190 float BlockStatement::getWeight (const GeneratorState& state)
192 if (state.getStatementDepth()+1 < state.getShaderParameters().maxStatementDepth)
194 if (isCurrentTopStatementBlock(state))
195 return 0.2f; // Low probability for anonymous blocks.
203 void BlockStatement::tokenize (GeneratorState& state, TokenStream& str) const
205 str << Token::LEFT_BRACE << Token::NEWLINE << Token::INDENT_INC;
207 for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
208 (*i)->tokenize(state, str);
210 str << Token::INDENT_DEC << Token::RIGHT_BRACE << Token::NEWLINE;
213 void BlockStatement::execute (ExecutionContext& execCtx) const
215 for (vector<Statement*>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
216 (*i)->execute(execCtx);
219 void ExpressionStatement::tokenize (GeneratorState& state, TokenStream& str) const
221 DE_ASSERT(m_expression);
222 m_expression->tokenize(state, str);
223 str << Token::SEMICOLON << Token::NEWLINE;
229 inline bool canDeclareVariable (const Variable* variable)
231 return variable->getStorage() == Variable::STORAGE_LOCAL;
234 bool hasDeclarableVars (const VariableManager& varMgr)
236 const vector<Variable*>& liveVars = varMgr.getLiveVariables();
237 for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
239 if (canDeclareVariable(*i))
247 DeclarationStatement::DeclarationStatement (GeneratorState& state, Variable* variable)
248 : m_variable (DE_NULL)
249 , m_expression (DE_NULL)
251 if (variable == DE_NULL)
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;
259 for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
261 if (canDeclareVariable(*i))
262 candidates.push_back(*i);
265 variable = state.getRandom().choose<Variable*>(candidates.begin(), candidates.end());
269 m_variable = variable;
271 const ValueEntry* value = state.getVariableManager().getValue(variable);
273 bool createInitializer = false;
275 switch (m_variable->getStorage())
277 case Variable::STORAGE_CONST:
279 createInitializer = true;
282 case Variable::STORAGE_LOCAL:
283 // initializer is always created if value isn't null.
284 createInitializer = value;
288 createInitializer = false;
292 if (createInitializer)
294 ExpressionGenerator generator(state);
296 // Take copy of value range for generating initializer expression
297 ValueRange valueRange = value->getValueRange();
299 // Declare (removes value entry)
300 state.getVariableManager().declareVariable(variable);
302 bool isConst = m_variable->getStorage() == Variable::STORAGE_CONST;
305 state.pushExpressionFlags(state.getExpressionFlags() | CONST_EXPR);
307 m_expression = generator.generate(valueRange, 1);
310 state.popExpressionFlags();
313 state.getVariableManager().declareVariable(variable);
316 DeclarationStatement::~DeclarationStatement (void)
321 float DeclarationStatement::getWeight (const GeneratorState& state)
323 if (!hasDeclarableVars(state.getVariableManager()))
326 if (!isCurrentTopStatementBlock(state))
329 return state.getProgramParameters().declarationStatementBaseWeight;
332 void DeclarationStatement::tokenize (GeneratorState& state, TokenStream& str) const
334 m_variable->tokenizeDeclaration(state, str);
339 m_expression->tokenize(state, str);
342 str << Token::SEMICOLON << Token::NEWLINE;
345 void DeclarationStatement::execute (ExecutionContext& execCtx) const
349 m_expression->evaluate(execCtx);
350 execCtx.getValue(m_variable) = m_expression->getValue().value();
354 ConditionalStatement::ConditionalStatement (GeneratorState&)
355 : m_condition (DE_NULL)
356 , m_trueStatement (DE_NULL)
357 , m_falseStatement (DE_NULL)
361 ConditionalStatement::~ConditionalStatement (void)
364 delete m_trueStatement;
365 delete m_falseStatement;
368 bool ConditionalStatement::isElseBlockRequired (const GeneratorState& state) const
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;
375 while (curStackNdx >= 0)
377 const ConditionalStatement* curParent = dynamic_cast<const ConditionalStatement*>(state.getStatementStackEntry(curStackNdx));
380 break; // Not a conditional statement - can end search here.
382 if (curChild == curParent->m_trueStatement && curParent->m_falseStatement)
383 return true; // Else block is mandatory.
386 curChild = curParent;
393 Statement* ConditionalStatement::createNextChild (GeneratorState& state)
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()))
398 // Construct false statement
399 state.getVariableManager().pushValueScope(m_conditionalScope);
400 m_falseStatement = createStatement(state);
402 return m_falseStatement;
404 else if (!m_trueStatement)
406 if (m_falseStatement)
408 // Pop previous value scope.
409 state.getVariableManager().popValueScope();
410 m_conditionalScope.clear();
413 // Construct true statement
414 state.getVariableManager().pushValueScope(m_conditionalScope);
415 m_trueStatement = createStatement(state);
417 return m_trueStatement;
421 // Pop conditional scope.
422 state.getVariableManager().popValueScope();
423 m_conditionalScope.clear();
426 DE_ASSERT(!m_condition);
428 ExpressionGenerator generator(state);
430 ValueRange range = ValueRange(VariableType::getScalarType(VariableType::TYPE_BOOL));
431 range.getMin().asBool() = false;
432 range.getMax().asBool() = true;
434 m_condition = generator.generate(range, 1);
436 return DE_NULL; // Done with this statement
443 bool isBlockStatement (const Statement* statement)
445 return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
448 bool isConditionalStatement (const Statement* statement)
450 return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
455 void ConditionalStatement::tokenize (GeneratorState& state, TokenStream& str) const
457 DE_ASSERT(m_condition && m_trueStatement);
460 str << Token::IF << Token::LEFT_PAREN;
461 m_condition->tokenize(state, str);
462 str << Token::RIGHT_PAREN << Token::NEWLINE;
464 // Statement executed if true
465 if (!isBlockStatement(m_trueStatement))
467 str << Token::INDENT_INC;
468 m_trueStatement->tokenize(state, str);
469 str << Token::INDENT_DEC;
472 m_trueStatement->tokenize(state, str);
474 if (m_falseStatement)
478 if (isConditionalStatement(m_falseStatement))
480 m_falseStatement->tokenize(state, str);
482 else if (isBlockStatement(m_falseStatement))
484 str << Token::NEWLINE;
485 m_falseStatement->tokenize(state, str);
489 str << Token::NEWLINE << Token::INDENT_INC;
490 m_falseStatement->tokenize(state, str);
491 str << Token::INDENT_DEC;
496 void ConditionalStatement::execute (ExecutionContext& execCtx) const
498 // Evaluate condition
499 m_condition->evaluate(execCtx);
501 ExecMaskStorage maskStorage; // Value might change when we are evaluating true block so we have to take a copy.
502 ExecValueAccess trueMask = maskStorage.getValue();
504 trueMask = m_condition->getValue().value();
506 // And mask, execute true statement and pop
507 execCtx.andExecutionMask(trueMask);
508 m_trueStatement->execute(execCtx);
509 execCtx.popExecutionMask();
511 if (m_falseStatement)
513 // Construct negated mask, execute false statement and pop
515 ExecValueAccess falseMask = tmp.getValue();
517 for (int i = 0; i < EXEC_VEC_WIDTH; i++)
518 falseMask.asBool(i) = !trueMask.asBool(i);
520 execCtx.andExecutionMask(falseMask);
521 m_falseStatement->execute(execCtx);
522 execCtx.popExecutionMask();
526 float ConditionalStatement::getWeight (const GeneratorState& state)
528 if (!state.getProgramParameters().useConditionals)
531 int availableLevels = state.getShaderParameters().maxStatementDepth - state.getStatementDepth();
532 return (availableLevels > 1) ? 1.0f : 0.0f;
535 AssignStatement::AssignStatement (const Variable* variable, Expression* value)
536 : m_variable (variable)
537 , m_valueExpr (value) // \note Takes ownership of value
541 AssignStatement::AssignStatement (GeneratorState& state, const Variable* variable, ConstValueRangeAccess valueRange)
542 : m_variable (variable)
543 , m_valueExpr (DE_NULL)
545 // Generate random value
546 ExpressionGenerator generator(state);
547 m_valueExpr = generator.generate(valueRange, 1);
550 AssignStatement::~AssignStatement (void)
555 void AssignStatement::tokenize (GeneratorState& state, TokenStream& str) const
557 str << Token(m_variable->getName()) << Token::EQUAL;
558 m_valueExpr->tokenize(state, str);
559 str << Token::SEMICOLON << Token::NEWLINE;
562 void AssignStatement::execute (ExecutionContext& execCtx) const
564 m_valueExpr->evaluate(execCtx);
565 assignMasked(execCtx.getValue(m_variable), m_valueExpr->getValue(), execCtx.getExecutionMask());