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 570