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 
isCurrentTopStatementBlock(const GeneratorState & state)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 
getWeight(const GeneratorState & state)44 template <class T> float		getWeight	(const GeneratorState& state)	{ return T::getWeight(state);	}
create(GeneratorState & 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 
chooseStatement(GeneratorState & state)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 
createStatement(GeneratorState & state)101 Statement* createStatement (GeneratorState& state)
102 {
103 	return chooseStatement(state)->create(state);
104 }
105 
106 } // anonymous
107 
Statement(void)108 Statement::Statement (void)
109 {
110 }
111 
~Statement(void)112 Statement::~Statement (void)
113 {
114 }
115 
ExpressionStatement(GeneratorState & state)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 
~ExpressionStatement(void)123 ExpressionStatement::~ExpressionStatement (void)
124 {
125 	delete m_expression;
126 }
127 
getWeight(const GeneratorState & state)128 float ExpressionStatement::getWeight (const GeneratorState& state)
129 {
130 	DE_UNREF(state);
131 	return 1.0f;
132 }
133 
execute(ExecutionContext & execCtx) const134 void ExpressionStatement::execute (ExecutionContext& execCtx) const
135 {
136 	m_expression->evaluate(execCtx);
137 }
138 
BlockStatement(GeneratorState & state)139 BlockStatement::BlockStatement (GeneratorState& state)
140 {
141 	init(state);
142 }
143 
init(GeneratorState & state)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 
~BlockStatement(void)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 
addChild(Statement * statement)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 
createNextChild(GeneratorState & state)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 
getWeight(const GeneratorState & state)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 
tokenize(GeneratorState & state,TokenStream & str) const203 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 
execute(ExecutionContext & execCtx) const213 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 
tokenize(GeneratorState & state,TokenStream & str) const219 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 
canDeclareVariable(const Variable * variable)229 inline bool canDeclareVariable (const Variable* variable)
230 {
231 	return variable->getStorage() == Variable::STORAGE_LOCAL;
232 }
233 
hasDeclarableVars(const VariableManager & varMgr)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 
DeclarationStatement(GeneratorState & state,Variable * variable)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 
~DeclarationStatement(void)317 DeclarationStatement::~DeclarationStatement (void)
318 {
319 	delete m_expression;
320 }
321 
getWeight(const GeneratorState & state)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 
tokenize(GeneratorState & state,TokenStream & str) const333 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 
execute(ExecutionContext & execCtx) const346 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 
ConditionalStatement(GeneratorState &)355 ConditionalStatement::ConditionalStatement (GeneratorState&)
356 	: m_condition		(DE_NULL)
357 	, m_trueStatement	(DE_NULL)
358 	, m_falseStatement	(DE_NULL)
359 {
360 }
361 
~ConditionalStatement(void)362 ConditionalStatement::~ConditionalStatement (void)
363 {
364 	delete m_condition;
365 	delete m_trueStatement;
366 	delete m_falseStatement;
367 }
368 
isElseBlockRequired(const GeneratorState & state) const369 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 
createNextChild(GeneratorState & state)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 
isBlockStatement(const Statement * statement)444 bool isBlockStatement (const Statement* statement)
445 {
446 	return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
447 }
448 
isConditionalStatement(const Statement * statement)449 bool isConditionalStatement (const Statement* statement)
450 {
451 	return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
452 }
453 
454 } // anonymous
455 
tokenize(GeneratorState & state,TokenStream & str) const456 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 
execute(ExecutionContext & execCtx) const497 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 
getWeight(const GeneratorState & state)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 
AssignStatement(const Variable * variable,Expression * value)536 AssignStatement::AssignStatement (const Variable* variable, Expression* value)
537 	: m_variable	(variable)
538 	, m_valueExpr	(value)	// \note Takes ownership of value
539 {
540 }
541 
AssignStatement(GeneratorState & state,const Variable * variable,ConstValueRangeAccess valueRange)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 
~AssignStatement(void)551 AssignStatement::~AssignStatement (void)
552 {
553 	delete m_valueExpr;
554 }
555 
tokenize(GeneratorState & state,TokenStream & str) const556 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 
execute(ExecutionContext & execCtx) const563 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