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