xref: /aosp_15_r20/external/deqp/framework/randomshaders/rsgStatement.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 
44 template <class T>
getWeight(const GeneratorState & state)45 float getWeight(const GeneratorState &state)
46 {
47     return T::getWeight(state);
48 }
49 template <class T>
create(GeneratorState & state)50 Statement *create(GeneratorState &state)
51 {
52     return new T(state);
53 }
54 
55 struct StatementSpec
56 {
57     float (*getWeight)(const GeneratorState &state);
58     Statement *(*create)(GeneratorState &state);
59 };
60 
chooseStatement(GeneratorState & state)61 const StatementSpec *chooseStatement(GeneratorState &state)
62 {
63     static const StatementSpec statementSpecs[] = {{getWeight<BlockStatement>, create<BlockStatement>},
64                                                    {getWeight<ExpressionStatement>, create<ExpressionStatement>},
65                                                    {getWeight<DeclarationStatement>, create<DeclarationStatement>},
66                                                    {getWeight<ConditionalStatement>, create<ConditionalStatement>}};
67 
68     float weights[DE_LENGTH_OF_ARRAY(statementSpecs)];
69 
70     // Compute weights
71     float sum = 0.0f;
72     for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
73     {
74         weights[ndx] = statementSpecs[ndx].getWeight(state);
75         sum += weights[ndx];
76     }
77 
78     DE_ASSERT(sum > 0.0f);
79 
80     // Random number in range
81     float p = state.getRandom().getFloat(0.0f, sum);
82 
83     const StatementSpec *spec        = DE_NULL;
84     const StatementSpec *lastNonZero = DE_NULL;
85 
86     // Find element in that point
87     sum = 0.0f;
88     for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(statementSpecs); ndx++)
89     {
90         sum += weights[ndx];
91         if (p < sum)
92         {
93             spec = &statementSpecs[ndx];
94             break;
95         }
96         else if (weights[ndx] > 0.0f)
97             lastNonZero = &statementSpecs[ndx];
98     }
99 
100     if (!spec)
101         spec = lastNonZero;
102 
103     return spec;
104 }
105 
createStatement(GeneratorState & state)106 Statement *createStatement(GeneratorState &state)
107 {
108     return chooseStatement(state)->create(state);
109 }
110 
111 } // namespace
112 
Statement(void)113 Statement::Statement(void)
114 {
115 }
116 
~Statement(void)117 Statement::~Statement(void)
118 {
119 }
120 
ExpressionStatement(GeneratorState & state)121 ExpressionStatement::ExpressionStatement(GeneratorState &state) : m_expression(DE_NULL)
122 {
123     ExpressionGenerator generator(state);
124     m_expression = generator.generate(ValueRange(VariableType(VariableType::TYPE_VOID)));
125 }
126 
~ExpressionStatement(void)127 ExpressionStatement::~ExpressionStatement(void)
128 {
129     delete m_expression;
130 }
131 
getWeight(const GeneratorState & state)132 float ExpressionStatement::getWeight(const GeneratorState &state)
133 {
134     DE_UNREF(state);
135     return 1.0f;
136 }
137 
execute(ExecutionContext & execCtx) const138 void ExpressionStatement::execute(ExecutionContext &execCtx) const
139 {
140     m_expression->evaluate(execCtx);
141 }
142 
BlockStatement(GeneratorState & state)143 BlockStatement::BlockStatement(GeneratorState &state)
144 {
145     init(state);
146 }
147 
init(GeneratorState & state)148 void BlockStatement::init(GeneratorState &state)
149 {
150     // Select number of children statements to construct
151     m_numChildrenToCreate = state.getRandom().getInt(0, state.getShaderParameters().maxStatementsPerBlock);
152 
153     // Push scope
154     state.getVariableManager().pushVariableScope(m_scope);
155 }
156 
~BlockStatement(void)157 BlockStatement::~BlockStatement(void)
158 {
159     for (vector<Statement *>::iterator i = m_children.begin(); i != m_children.end(); i++)
160         delete *i;
161     m_children.clear();
162 }
163 
addChild(Statement * statement)164 void BlockStatement::addChild(Statement *statement)
165 {
166     try
167     {
168         m_children.push_back(statement);
169     }
170     catch (const std::exception &)
171     {
172         delete statement;
173         throw;
174     }
175 }
176 
createNextChild(GeneratorState & state)177 Statement *BlockStatement::createNextChild(GeneratorState &state)
178 {
179     if ((int)m_children.size() < m_numChildrenToCreate)
180     {
181         // Select and create a new child
182         Statement *child = createStatement(state);
183         addChild(child);
184         return child;
185     }
186     else
187     {
188         // Done, pop scope
189         state.getVariableManager().popVariableScope();
190         return DE_NULL;
191     }
192 }
193 
getWeight(const GeneratorState & state)194 float BlockStatement::getWeight(const GeneratorState &state)
195 {
196     if (state.getStatementDepth() + 1 < state.getShaderParameters().maxStatementDepth)
197     {
198         if (isCurrentTopStatementBlock(state))
199             return 0.2f; // Low probability for anonymous blocks.
200         else
201             return 1.0f;
202     }
203     else
204         return 0.0f;
205 }
206 
tokenize(GeneratorState & state,TokenStream & str) const207 void BlockStatement::tokenize(GeneratorState &state, TokenStream &str) const
208 {
209     str << Token::LEFT_BRACE << Token::NEWLINE << Token::INDENT_INC;
210 
211     for (vector<Statement *>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
212         (*i)->tokenize(state, str);
213 
214     str << Token::INDENT_DEC << Token::RIGHT_BRACE << Token::NEWLINE;
215 }
216 
execute(ExecutionContext & execCtx) const217 void BlockStatement::execute(ExecutionContext &execCtx) const
218 {
219     for (vector<Statement *>::const_reverse_iterator i = m_children.rbegin(); i != m_children.rend(); i++)
220         (*i)->execute(execCtx);
221 }
222 
tokenize(GeneratorState & state,TokenStream & str) const223 void ExpressionStatement::tokenize(GeneratorState &state, TokenStream &str) const
224 {
225     DE_ASSERT(m_expression);
226     m_expression->tokenize(state, str);
227     str << Token::SEMICOLON << Token::NEWLINE;
228 }
229 
230 namespace
231 {
232 
canDeclareVariable(const Variable * variable)233 inline bool canDeclareVariable(const Variable *variable)
234 {
235     return variable->getStorage() == Variable::STORAGE_LOCAL;
236 }
237 
hasDeclarableVars(const VariableManager & varMgr)238 bool hasDeclarableVars(const VariableManager &varMgr)
239 {
240     const vector<Variable *> &liveVars = varMgr.getLiveVariables();
241     for (vector<Variable *>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
242     {
243         if (canDeclareVariable(*i))
244             return true;
245     }
246     return false;
247 }
248 
249 } // namespace
250 
DeclarationStatement(GeneratorState & state,Variable * variable)251 DeclarationStatement::DeclarationStatement(GeneratorState &state, Variable *variable)
252     : m_variable(DE_NULL)
253     , m_expression(DE_NULL)
254 {
255     if (variable == DE_NULL)
256     {
257         // Choose random
258         // \todo [2011-02-03 pyry] Allocate a new here?
259         // \todo [2011-05-26 pyry] Weights?
260         const vector<Variable *> &liveVars = state.getVariableManager().getLiveVariables();
261         vector<Variable *> candidates;
262 
263         for (vector<Variable *>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
264         {
265             if (canDeclareVariable(*i))
266                 candidates.push_back(*i);
267         }
268 
269         variable = state.getRandom().choose<Variable *>(candidates.begin(), candidates.end());
270     }
271 
272     DE_ASSERT(variable);
273     m_variable = variable;
274 
275     const ValueEntry *value = state.getVariableManager().getValue(variable);
276 
277     bool createInitializer = false;
278 
279     switch (m_variable->getStorage())
280     {
281     case Variable::STORAGE_CONST:
282         DE_ASSERT(value);
283         createInitializer = true;
284         break;
285 
286     case Variable::STORAGE_LOCAL:
287         // initializer is always created if value isn't null.
288         createInitializer = value;
289         break;
290 
291     default:
292         createInitializer = false;
293         break;
294     }
295 
296     if (createInitializer)
297     {
298         ExpressionGenerator generator(state);
299 
300         // Take copy of value range for generating initializer expression
301         ValueRange valueRange = value->getValueRange();
302 
303         // Declare (removes value entry)
304         state.getVariableManager().declareVariable(variable);
305 
306         bool isConst = m_variable->getStorage() == Variable::STORAGE_CONST;
307 
308         if (isConst)
309             state.pushExpressionFlags(state.getExpressionFlags() | CONST_EXPR);
310 
311         m_expression = generator.generate(valueRange, 1);
312 
313         if (isConst)
314             state.popExpressionFlags();
315     }
316     else
317         state.getVariableManager().declareVariable(variable);
318 }
319 
~DeclarationStatement(void)320 DeclarationStatement::~DeclarationStatement(void)
321 {
322     delete m_expression;
323 }
324 
getWeight(const GeneratorState & state)325 float DeclarationStatement::getWeight(const GeneratorState &state)
326 {
327     if (!hasDeclarableVars(state.getVariableManager()))
328         return 0.0f;
329 
330     if (!isCurrentTopStatementBlock(state))
331         return 0.0f;
332 
333     return state.getProgramParameters().declarationStatementBaseWeight;
334 }
335 
tokenize(GeneratorState & state,TokenStream & str) const336 void DeclarationStatement::tokenize(GeneratorState &state, TokenStream &str) const
337 {
338     m_variable->tokenizeDeclaration(state, str);
339 
340     if (m_expression)
341     {
342         str << Token::EQUAL;
343         m_expression->tokenize(state, str);
344     }
345 
346     str << Token::SEMICOLON << Token::NEWLINE;
347 }
348 
execute(ExecutionContext & execCtx) const349 void DeclarationStatement::execute(ExecutionContext &execCtx) const
350 {
351     if (m_expression)
352     {
353         m_expression->evaluate(execCtx);
354         execCtx.getValue(m_variable) = m_expression->getValue().value();
355     }
356 }
357 
ConditionalStatement(GeneratorState &)358 ConditionalStatement::ConditionalStatement(GeneratorState &)
359     : m_condition(DE_NULL)
360     , m_trueStatement(DE_NULL)
361     , m_falseStatement(DE_NULL)
362 {
363 }
364 
~ConditionalStatement(void)365 ConditionalStatement::~ConditionalStatement(void)
366 {
367     delete m_condition;
368     delete m_trueStatement;
369     delete m_falseStatement;
370 }
371 
isElseBlockRequired(const GeneratorState & state) const372 bool ConditionalStatement::isElseBlockRequired(const GeneratorState &state) const
373 {
374     // If parent is conditional statement with else block and this is the true statement,
375     // else block must be generated or otherwise parent "else" will end up parsed as else statement for this if.
376     const ConditionalStatement *curChild = this;
377     int curStackNdx                      = state.getStatementDepth() - 2;
378 
379     while (curStackNdx >= 0)
380     {
381         const ConditionalStatement *curParent =
382             dynamic_cast<const ConditionalStatement *>(state.getStatementStackEntry(curStackNdx));
383 
384         if (!curParent)
385             break; // Not a conditional statement - can end search here.
386 
387         if (curChild == curParent->m_trueStatement && curParent->m_falseStatement)
388             return true; // Else block is mandatory.
389 
390         // Continue search.
391         curChild = curParent;
392         curStackNdx -= 1;
393     }
394 
395     return false;
396 }
397 
createNextChild(GeneratorState & state)398 Statement *ConditionalStatement::createNextChild(GeneratorState &state)
399 {
400     // If has neither true or false statements, choose randomly whether to create false block.
401     if (!m_falseStatement && !m_trueStatement && (isElseBlockRequired(state) || state.getRandom().getBool()))
402     {
403         // Construct false statement
404         state.getVariableManager().pushValueScope(m_conditionalScope);
405         m_falseStatement = createStatement(state);
406 
407         return m_falseStatement;
408     }
409     else if (!m_trueStatement)
410     {
411         if (m_falseStatement)
412         {
413             // Pop previous value scope.
414             state.getVariableManager().popValueScope();
415             m_conditionalScope.clear();
416         }
417 
418         // Construct true statement
419         state.getVariableManager().pushValueScope(m_conditionalScope);
420         m_trueStatement = createStatement(state);
421 
422         return m_trueStatement;
423     }
424     else
425     {
426         // Pop conditional scope.
427         state.getVariableManager().popValueScope();
428         m_conditionalScope.clear();
429 
430         // Create condition
431         DE_ASSERT(!m_condition);
432 
433         ExpressionGenerator generator(state);
434 
435         ValueRange range        = ValueRange(VariableType::getScalarType(VariableType::TYPE_BOOL));
436         range.getMin().asBool() = false;
437         range.getMax().asBool() = true;
438 
439         m_condition = generator.generate(range, 1);
440 
441         return DE_NULL; // Done with this statement
442     }
443 }
444 
445 namespace
446 {
447 
isBlockStatement(const Statement * statement)448 bool isBlockStatement(const Statement *statement)
449 {
450     return dynamic_cast<const BlockStatement *>(statement) != DE_NULL;
451 }
452 
isConditionalStatement(const Statement * statement)453 bool isConditionalStatement(const Statement *statement)
454 {
455     return dynamic_cast<const ConditionalStatement *>(statement) != DE_NULL;
456 }
457 
458 } // namespace
459 
tokenize(GeneratorState & state,TokenStream & str) const460 void ConditionalStatement::tokenize(GeneratorState &state, TokenStream &str) const
461 {
462     DE_ASSERT(m_condition && m_trueStatement);
463 
464     // if (condition)
465     str << Token::IF << Token::LEFT_PAREN;
466     m_condition->tokenize(state, str);
467     str << Token::RIGHT_PAREN << Token::NEWLINE;
468 
469     // Statement executed if true
470     if (!isBlockStatement(m_trueStatement))
471     {
472         str << Token::INDENT_INC;
473         m_trueStatement->tokenize(state, str);
474         str << Token::INDENT_DEC;
475     }
476     else
477         m_trueStatement->tokenize(state, str);
478 
479     if (m_falseStatement)
480     {
481         str << Token::ELSE;
482 
483         if (isConditionalStatement(m_falseStatement))
484         {
485             m_falseStatement->tokenize(state, str);
486         }
487         else if (isBlockStatement(m_falseStatement))
488         {
489             str << Token::NEWLINE;
490             m_falseStatement->tokenize(state, str);
491         }
492         else
493         {
494             str << Token::NEWLINE << Token::INDENT_INC;
495             m_falseStatement->tokenize(state, str);
496             str << Token::INDENT_DEC;
497         }
498     }
499 }
500 
execute(ExecutionContext & execCtx) const501 void ConditionalStatement::execute(ExecutionContext &execCtx) const
502 {
503     // Evaluate condition
504     m_condition->evaluate(execCtx);
505 
506     ExecMaskStorage maskStorage; // Value might change when we are evaluating true block so we have to take a copy.
507     ExecValueAccess trueMask = maskStorage.getValue();
508 
509     trueMask = m_condition->getValue().value();
510 
511     // And mask, execute true statement and pop
512     execCtx.andExecutionMask(trueMask);
513     m_trueStatement->execute(execCtx);
514     execCtx.popExecutionMask();
515 
516     if (m_falseStatement)
517     {
518         // Construct negated mask, execute false statement and pop
519         ExecMaskStorage tmp;
520         ExecValueAccess falseMask = tmp.getValue();
521 
522         for (int i = 0; i < EXEC_VEC_WIDTH; i++)
523             falseMask.asBool(i) = !trueMask.asBool(i);
524 
525         execCtx.andExecutionMask(falseMask);
526         m_falseStatement->execute(execCtx);
527         execCtx.popExecutionMask();
528     }
529 }
530 
getWeight(const GeneratorState & state)531 float ConditionalStatement::getWeight(const GeneratorState &state)
532 {
533     if (!state.getProgramParameters().useConditionals)
534         return 0.0f;
535 
536     int availableLevels = state.getShaderParameters().maxStatementDepth - state.getStatementDepth();
537     return (availableLevels > 1) ? 1.0f : 0.0f;
538 }
539 
AssignStatement(const Variable * variable,Expression * value)540 AssignStatement::AssignStatement(const Variable *variable, Expression *value)
541     : m_variable(variable)
542     , m_valueExpr(value) // \note Takes ownership of value
543 {
544 }
545 
AssignStatement(GeneratorState & state,const Variable * variable,ConstValueRangeAccess valueRange)546 AssignStatement::AssignStatement(GeneratorState &state, const Variable *variable, ConstValueRangeAccess valueRange)
547     : m_variable(variable)
548     , m_valueExpr(DE_NULL)
549 {
550     // Generate random value
551     ExpressionGenerator generator(state);
552     m_valueExpr = generator.generate(valueRange, 1);
553 }
554 
~AssignStatement(void)555 AssignStatement::~AssignStatement(void)
556 {
557     delete m_valueExpr;
558 }
559 
tokenize(GeneratorState & state,TokenStream & str) const560 void AssignStatement::tokenize(GeneratorState &state, TokenStream &str) const
561 {
562     str << Token(m_variable->getName()) << Token::EQUAL;
563     m_valueExpr->tokenize(state, str);
564     str << Token::SEMICOLON << Token::NEWLINE;
565 }
566 
execute(ExecutionContext & execCtx) const567 void AssignStatement::execute(ExecutionContext &execCtx) const
568 {
569     m_valueExpr->evaluate(execCtx);
570     assignMasked(execCtx.getValue(m_variable), m_valueExpr->getValue(), execCtx.getExecutionMask());
571 }
572 
573 } // namespace rsg
574