Home | History | Annotate | Download | only in randomshaders
      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