• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 			// 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 
~DeclarationStatement(void)316 DeclarationStatement::~DeclarationStatement (void)
317 {
318 	delete m_expression;
319 }
320 
getWeight(const GeneratorState & state)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 
tokenize(GeneratorState & state,TokenStream & str) const332 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 
execute(ExecutionContext & execCtx) const345 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 
ConditionalStatement(GeneratorState &)354 ConditionalStatement::ConditionalStatement (GeneratorState&)
355 	: m_condition		(DE_NULL)
356 	, m_trueStatement	(DE_NULL)
357 	, m_falseStatement	(DE_NULL)
358 {
359 }
360 
~ConditionalStatement(void)361 ConditionalStatement::~ConditionalStatement (void)
362 {
363 	delete m_condition;
364 	delete m_trueStatement;
365 	delete m_falseStatement;
366 }
367 
isElseBlockRequired(const GeneratorState & state) const368 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 
createNextChild(GeneratorState & state)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 
isBlockStatement(const Statement * statement)443 bool isBlockStatement (const Statement* statement)
444 {
445 	return dynamic_cast<const BlockStatement*>(statement) != DE_NULL;
446 }
447 
isConditionalStatement(const Statement * statement)448 bool isConditionalStatement (const Statement* statement)
449 {
450 	return dynamic_cast<const ConditionalStatement*>(statement) != DE_NULL;
451 }
452 
453 } // anonymous
454 
tokenize(GeneratorState & state,TokenStream & str) const455 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 
execute(ExecutionContext & execCtx) const496 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 
getWeight(const GeneratorState & state)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 
AssignStatement(const Variable * variable,Expression * value)535 AssignStatement::AssignStatement (const Variable* variable, Expression* value)
536 	: m_variable	(variable)
537 	, m_valueExpr	(value)	// \note Takes ownership of value
538 {
539 }
540 
AssignStatement(GeneratorState & state,const Variable * variable,ConstValueRangeAccess valueRange)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 
~AssignStatement(void)550 AssignStatement::~AssignStatement (void)
551 {
552 	delete m_valueExpr;
553 }
554 
tokenize(GeneratorState & state,TokenStream & str) const555 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 
execute(ExecutionContext & execCtx) const562 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
569