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