xref: /aosp_15_r20/external/deqp/framework/randomshaders/rsgShaderGenerator.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 Shader generator.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "rsgShaderGenerator.hpp"
25 #include "rsgFunctionGenerator.hpp"
26 #include "rsgToken.hpp"
27 #include "rsgPrettyPrinter.hpp"
28 #include "rsgUtils.hpp"
29 #include "deString.h"
30 
31 #include <iterator>
32 
33 using std::string;
34 using std::vector;
35 
36 namespace rsg
37 {
38 
ShaderGenerator(GeneratorState & state)39 ShaderGenerator::ShaderGenerator(GeneratorState &state) : m_state(state), m_varManager(state.getNameAllocator())
40 {
41     state.setVariableManager(m_varManager);
42 }
43 
~ShaderGenerator(void)44 ShaderGenerator::~ShaderGenerator(void)
45 {
46 }
47 
48 namespace
49 {
50 
getFragColorName(const GeneratorState & state)51 const char *getFragColorName(const GeneratorState &state)
52 {
53     switch (state.getProgramParameters().version)
54     {
55     case VERSION_100:
56         return "gl_FragColor";
57     case VERSION_300:
58         return "dEQP_FragColor";
59     default:
60         DE_ASSERT(false);
61         return DE_NULL;
62     }
63 }
64 
createAssignment(BlockStatement & block,const Variable * dstVar,const Variable * srcVar)65 void createAssignment(BlockStatement &block, const Variable *dstVar, const Variable *srcVar)
66 {
67     VariableRead *varRead = new VariableRead(srcVar);
68     try
69     {
70         block.addChild(new AssignStatement(dstVar, varRead));
71     }
72     catch (const std::exception &)
73     {
74         delete varRead;
75         throw;
76     }
77 }
78 
findByName(VariableManager & varManager,const char * name)79 const ValueEntry *findByName(VariableManager &varManager, const char *name)
80 {
81     AnyEntry::Iterator iter = varManager.getBegin<AnyEntry>();
82     AnyEntry::Iterator end  = varManager.getEnd<AnyEntry>();
83     for (; iter != end; iter++)
84     {
85         const ValueEntry *entry = *iter;
86         if (deStringEqual(entry->getVariable()->getName(), name))
87             return entry;
88     }
89     return DE_NULL;
90 }
91 
genVertexPassthrough(GeneratorState & state,Shader & shader)92 void genVertexPassthrough(GeneratorState &state, Shader &shader)
93 {
94     // Create copies from shader inputs to outputs
95     vector<const ValueEntry *> entries;
96     std::copy(state.getVariableManager().getBegin<AnyEntry>(), state.getVariableManager().getEnd<AnyEntry>(),
97               std::inserter(entries, entries.begin()));
98 
99     for (vector<const ValueEntry *>::const_iterator i = entries.begin(); i != entries.end(); i++)
100     {
101         const ValueEntry *entry = *i;
102         const Variable *outVar  = entry->getVariable();
103         std::string inVarName;
104 
105         if (outVar->getStorage() != Variable::STORAGE_SHADER_OUT)
106             continue;
107 
108         // Name: a_[name], remove v_ -prefix if such exists
109         inVarName = "a_";
110         if (deStringBeginsWith(outVar->getName(), "v_"))
111             inVarName += (outVar->getName() + 2);
112         else
113             inVarName += outVar->getName();
114 
115         Variable *inVar =
116             state.getVariableManager().allocate(outVar->getType(), Variable::STORAGE_SHADER_IN, inVarName.c_str());
117 
118         // Update value range. This will be stored into shader input info.
119         state.getVariableManager().setValue(inVar, entry->getValueRange());
120 
121         // Add assignment from input to output into main() body
122         createAssignment(shader.getMain().getBody(), entry->getVariable(), inVar);
123     }
124 }
125 
genFragmentPassthrough(GeneratorState & state,Shader & shader)126 void genFragmentPassthrough(GeneratorState &state, Shader &shader)
127 {
128     // Add simple gl_FragColor = v_color; assignment
129     const ValueEntry *fragColorEntry = findByName(state.getVariableManager(), getFragColorName(state));
130     TCU_CHECK(fragColorEntry);
131 
132     Variable *inColorVariable = state.getVariableManager().allocate(fragColorEntry->getVariable()->getType(),
133                                                                     Variable::STORAGE_SHADER_IN, "v_color");
134 
135     state.getVariableManager().setValue(inColorVariable, fragColorEntry->getValueRange());
136     createAssignment(shader.getMain().getBody(), fragColorEntry->getVariable(), inColorVariable);
137 }
138 
139 // Sets undefined (-inf..inf) components to some meaningful values. Used for sanitizing final shader input value ranges.
fillUndefinedComponents(ValueRangeAccess valueRange)140 void fillUndefinedComponents(ValueRangeAccess valueRange)
141 {
142     VariableType::Type baseType = valueRange.getType().getBaseType();
143     TCU_CHECK(baseType == VariableType::TYPE_FLOAT || baseType == VariableType::TYPE_INT ||
144               baseType == VariableType::TYPE_BOOL);
145 
146     for (int elemNdx = 0; elemNdx < valueRange.getType().getNumElements(); elemNdx++)
147     {
148         if (isUndefinedValueRange(valueRange.component(elemNdx)))
149         {
150             ValueAccess min = valueRange.component(elemNdx).getMin();
151             ValueAccess max = valueRange.component(elemNdx).getMax();
152 
153             switch (baseType)
154             {
155             case VariableType::TYPE_FLOAT:
156                 min = 0.0f;
157                 max = 1.0f;
158                 break;
159             case VariableType::TYPE_INT:
160                 min = 0;
161                 max = 1;
162                 break;
163             case VariableType::TYPE_BOOL:
164                 min = false;
165                 max = true;
166                 break;
167             default:
168                 DE_ASSERT(false);
169             }
170         }
171     }
172 }
173 
fillUndefinedShaderInputs(vector<ShaderInput * > & inputs)174 void fillUndefinedShaderInputs(vector<ShaderInput *> &inputs)
175 {
176     for (vector<ShaderInput *>::iterator i = inputs.begin(); i != inputs.end(); i++)
177     {
178         if (!(*i)->getVariable()->getType().isSampler()) // Samplers are assigned at program-level.
179             fillUndefinedComponents((*i)->getValueRange());
180     }
181 }
182 
183 } // namespace
184 
generate(const ShaderParameters & shaderParams,Shader & shader,const vector<ShaderInput * > & outputs)185 void ShaderGenerator::generate(const ShaderParameters &shaderParams, Shader &shader,
186                                const vector<ShaderInput *> &outputs)
187 {
188     // Global scopes
189     VariableScope &globalVariableScope = shader.getGlobalScope();
190     ValueScope globalValueScope;
191 
192     // Init state
193     m_state.setShader(shaderParams, shader);
194     DE_ASSERT(m_state.getExpressionFlags() == 0);
195 
196     // Reserve some scalars for gl_Position & dEQP_Position
197     ReservedScalars reservedScalars;
198     if (shader.getType() == Shader::TYPE_VERTEX)
199         m_state.getVariableManager().reserve(reservedScalars, 4 * 2);
200 
201     // Push global scopes
202     m_varManager.pushVariableScope(globalVariableScope);
203     m_varManager.pushValueScope(globalValueScope);
204 
205     // Init shader outputs.
206     {
207         for (vector<ShaderInput *>::const_iterator i = outputs.begin(); i != outputs.end(); i++)
208         {
209             const ShaderInput *input = *i;
210             Variable *variable       = m_state.getVariableManager().allocate(
211                 input->getVariable()->getType(), Variable::STORAGE_SHADER_OUT, input->getVariable()->getName());
212 
213             m_state.getVariableManager().setValue(variable, input->getValueRange());
214         }
215 
216         if (shader.getType() == Shader::TYPE_FRAGMENT)
217         {
218             // gl_FragColor
219             // \todo [2011-11-22 pyry] Multiple outputs from fragment shader!
220             Variable *fragColorVar = m_state.getVariableManager().allocate(
221                 VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_OUT, getFragColorName(m_state));
222             ValueRange valueRange(fragColorVar->getType());
223 
224             valueRange.getMin() = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
225             valueRange.getMax() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
226 
227             fragColorVar->setLayoutLocation(0); // Bind color output to location 0 (applies to GLSL ES 3.0 onwards).
228 
229             m_state.getVariableManager().setValue(fragColorVar, valueRange.asAccess());
230         }
231     }
232 
233     // Construct shader code.
234     {
235         Function &main = shader.getMain();
236         main.setReturnType(VariableType(VariableType::TYPE_VOID));
237 
238         if (shaderParams.randomize)
239         {
240             FunctionGenerator funcGen(m_state, main);
241 
242             // Mandate assignment into to all shader outputs in main()
243             const vector<Variable *> &liveVars = globalVariableScope.getLiveVariables();
244             for (vector<Variable *>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++)
245             {
246                 Variable *variable = *i;
247                 if (variable->getStorage() == Variable::STORAGE_SHADER_OUT)
248                     funcGen.requireAssignment(variable);
249             }
250 
251             funcGen.generate();
252         }
253         else
254         {
255             if (shader.getType() == Shader::TYPE_VERTEX)
256                 genVertexPassthrough(m_state, shader);
257             else
258             {
259                 DE_ASSERT(shader.getType() == Shader::TYPE_FRAGMENT);
260                 genFragmentPassthrough(m_state, shader);
261             }
262         }
263 
264         if (shader.getType() == Shader::TYPE_VERTEX)
265         {
266             // Add gl_Position = dEQP_Position;
267             m_state.getVariableManager().release(reservedScalars);
268 
269             Variable *glPosVariable = m_state.getVariableManager().allocate(
270                 VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_OUT, "gl_Position");
271             Variable *qpPosVariable = m_state.getVariableManager().allocate(
272                 VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_IN, "dEQP_Position");
273 
274             ValueRange valueRange(glPosVariable->getType());
275 
276             valueRange.getMin() = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
277             valueRange.getMax() = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
278 
279             m_state.getVariableManager().setValue(
280                 qpPosVariable,
281                 valueRange
282                     .asAccess()); // \todo [2011-05-24 pyry] No expression should be able to use gl_Position or dEQP_Position..
283 
284             createAssignment(main.getBody(), glPosVariable, qpPosVariable);
285         }
286     }
287 
288     // Declare live global variables.
289     {
290         vector<Variable *> liveVariables;
291         std::copy(globalVariableScope.getLiveVariables().begin(), globalVariableScope.getLiveVariables().end(),
292                   std::inserter(liveVariables, liveVariables.begin()));
293 
294         vector<Variable *> createDeclarationStatementVars;
295 
296         for (vector<Variable *>::iterator i = liveVariables.begin(); i != liveVariables.end(); i++)
297         {
298             Variable *variable = *i;
299             const char *name   = variable->getName();
300             bool declare       = !deStringBeginsWith(name, "gl_"); // Do not declare built-in types.
301 
302             // Create input entries (store value range) if necessary
303             vector<ShaderInput *> &inputs   = shader.getInputs();
304             vector<ShaderInput *> &uniforms = shader.getUniforms();
305 
306             switch (variable->getStorage())
307             {
308             case Variable::STORAGE_SHADER_IN:
309             {
310                 const ValueEntry *value = m_state.getVariableManager().getValue(variable);
311 
312                 inputs.reserve(inputs.size() + 1);
313                 inputs.push_back(new ShaderInput(variable, value->getValueRange()));
314                 break;
315             }
316 
317             case Variable::STORAGE_UNIFORM:
318             {
319                 const ValueEntry *value = m_state.getVariableManager().getValue(variable);
320 
321                 uniforms.reserve(uniforms.size() + 1);
322                 uniforms.push_back(new ShaderInput(variable, value->getValueRange()));
323                 break;
324             }
325 
326             default:
327                 break;
328             }
329 
330             if (declare)
331                 createDeclarationStatementVars.push_back(variable);
332             else
333             {
334                 // Just move to global scope without declaration statement.
335                 m_state.getVariableManager().declareVariable(variable);
336             }
337         }
338 
339         // All global initializers must be constant expressions, no variable allocation is allowed
340         DE_ASSERT(m_state.getExpressionFlags() == 0);
341         m_state.pushExpressionFlags(CONST_EXPR | NO_VAR_ALLOCATION);
342 
343         // Create declaration statements
344         for (vector<Variable *>::iterator i = createDeclarationStatementVars.begin();
345              i != createDeclarationStatementVars.end(); i++)
346         {
347             shader.getGlobalStatements().reserve(shader.getGlobalStatements().size());
348             shader.getGlobalStatements().push_back(new DeclarationStatement(m_state, *i));
349         }
350 
351         m_state.popExpressionFlags();
352     }
353 
354     // Pop global scopes
355     m_varManager.popVariableScope();
356     m_varManager.popValueScope();
357 
358     // Fill undefined (unused) components in inputs with unused values
359     fillUndefinedShaderInputs(shader.getInputs());
360     fillUndefinedShaderInputs(shader.getUniforms());
361 
362     // Tokenize shader and write source
363     {
364         TokenStream tokenStr;
365         shader.tokenize(m_state, tokenStr);
366 
367         std::ostringstream str;
368         PrettyPrinter printer(str);
369 
370         // Append #version if necessary.
371         if (m_state.getProgramParameters().version == VERSION_300)
372             str << "#version 300 es\n";
373 
374         printer.append(tokenStr);
375         shader.setSource(str.str().c_str());
376     }
377 }
378 
379 } // namespace rsg
380