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