Merge in changes from Khronos Vulkan CTS repo
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderLoopTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and/or associated documentation files (the
11  * "Materials"), to deal in the Materials without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Materials, and to
14  * permit persons to whom the Materials are furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice(s) and this permission notice shall be included
18  * in all copies or substantial portions of the Materials.
19  *
20  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
27  *
28  *//*!
29  * \file
30  * \brief Shader loop tests.
31  *//*--------------------------------------------------------------------*/
32
33 #include "vktShaderRenderLoopTests.hpp"
34
35 #include "vktShaderRender.hpp"
36 #include "tcuStringTemplate.hpp"
37 #include "gluShaderUtil.hpp"
38 #include "deStringUtil.hpp"
39
40 #include <map>
41
42 namespace vkt
43 {
44 namespace sr
45 {
46 namespace
47 {
48
49 static const char* getIntUniformName (int number)
50 {
51         switch (number)
52         {
53                 case 0:         return "ui_zero";
54                 case 1:         return "ui_one";
55                 case 2:         return "ui_two";
56                 case 3:         return "ui_three";
57                 case 4:         return "ui_four";
58                 case 5:         return "ui_five";
59                 case 6:         return "ui_six";
60                 case 7:         return "ui_seven";
61                 case 8:         return "ui_eight";
62                 case 101:       return "ui_oneHundredOne";
63                 default:
64                         DE_ASSERT(false);
65                         return "";
66         }
67 }
68
69 static BaseUniformType getIntUniformType(int number)
70 {
71         switch (number)
72         {
73                 case 1:         return UI_ONE;
74                 case 2:         return UI_TWO;
75                 case 3:         return UI_THREE;
76                 case 4:         return UI_FOUR;
77                 case 5:         return UI_FIVE;
78                 case 6:         return UI_SIX;
79                 case 7:         return UI_SEVEN;
80                 case 8:         return UI_EIGHT;
81                 default:
82                         DE_ASSERT(false);
83                         return UB_FALSE;
84         }
85 }
86
87 static const char* getFloatFractionUniformName (int number)
88 {
89         switch (number)
90         {
91                 case 1: return "uf_one";
92                 case 2: return "uf_half";
93                 case 3: return "uf_third";
94                 case 4: return "uf_fourth";
95                 case 5: return "uf_fifth";
96                 case 6: return "uf_sixth";
97                 case 7: return "uf_seventh";
98                 case 8: return "uf_eight";
99                 default:
100                         DE_ASSERT(false);
101                         return "";
102         }
103 }
104
105 static BaseUniformType getFloatFractionUniformType(int number)
106 {
107         switch (number)
108         {
109                 case 1:         return UF_ONE;
110                 case 2:         return UF_HALF;
111                 case 3:         return UF_THIRD;
112                 case 4:         return UF_FOURTH;
113                 case 5:         return UF_FIFTH;
114                 case 6:         return UF_SIXTH;
115                 case 7:         return UF_SEVENTH;
116                 case 8:         return UF_EIGHTH;
117                 default:
118                         DE_ASSERT(false);
119                         return UB_FALSE;
120         }
121 }
122
123 enum LoopType
124 {
125         LOOPTYPE_FOR = 0,
126         LOOPTYPE_WHILE,
127         LOOPTYPE_DO_WHILE,
128         LOOPTYPE_LAST
129 };
130
131 static const char* getLoopTypeName (LoopType loopType)
132 {
133         static const char* s_names[] =
134         {
135                 "for",
136                 "while",
137                 "do_while"
138         };
139
140         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPTYPE_LAST);
141         DE_ASSERT(deInBounds32((int)loopType, 0, LOOPTYPE_LAST));
142         return s_names[(int)loopType];
143 }
144
145 enum LoopCountType
146 {
147         LOOPCOUNT_CONSTANT = 0,
148         LOOPCOUNT_UNIFORM,
149         LOOPCOUNT_DYNAMIC,
150
151         LOOPCOUNT_LAST
152 };
153
154 // Repeated with for, while, do-while. Examples given as 'for' loops.
155 // Repeated for const, uniform, dynamic loops.
156 enum LoopCase
157 {
158                 LOOPCASE_EMPTY_BODY = 0,                                                        // for (...) { }
159                 LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST,       // for (...) { break; <body>; }
160                 LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST,        // for (...) { <body>; break; }
161                 LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK,                       // for (...) { <body>; if (cond) break; }
162                 LOOPCASE_SINGLE_STATEMENT,                                                      // for (...) statement;
163                 LOOPCASE_COMPOUND_STATEMENT,                                            // for (...) { statement; statement; }
164                 LOOPCASE_SEQUENCE_STATEMENT,                                            // for (...) statement, statement;
165                 LOOPCASE_NO_ITERATIONS,                                                         // for (i=0; i<0; i++) ...
166                 LOOPCASE_SINGLE_ITERATION,                                                      // for (i=0; i<1; i++) ...
167                 LOOPCASE_SELECT_ITERATION_COUNT,                                        // for (i=0; i<a?b:c; i++) ...
168                 LOOPCASE_CONDITIONAL_CONTINUE,                                          // for (...) { if (cond) continue; }
169                 LOOPCASE_UNCONDITIONAL_CONTINUE,                                        // for (...) { <body>; continue; }
170                 LOOPCASE_ONLY_CONTINUE,                                                         // for (...) { continue; }
171                 LOOPCASE_DOUBLE_CONTINUE,                                                       // for (...) { if (cond) continue; <body>; $
172                 LOOPCASE_CONDITIONAL_BREAK,                                                     // for (...) { if (cond) break; }
173                 LOOPCASE_UNCONDITIONAL_BREAK,                                           // for (...) { <body>; break; }
174                 LOOPCASE_PRE_INCREMENT,                                                         // for (...; ++i) { <body>; }
175                 LOOPCASE_POST_INCREMENT,                                                        // for (...; i++) { <body>; }
176                 LOOPCASE_MIXED_BREAK_CONTINUE,
177                 LOOPCASE_VECTOR_COUNTER,                                                        // for (ivec3 ndx = ...; ndx.x < ndx.y; ndx$
178                 LOOPCASE_101_ITERATIONS,                                                        // loop for 101 iterations
179                 LOOPCASE_SEQUENCE,                                                                      // two loops in sequence
180                 LOOPCASE_NESTED,                                                                        // two nested loops
181                 LOOPCASE_NESTED_SEQUENCE,                                                       // two loops in sequence nested inside a th$
182                 LOOPCASE_NESTED_TRICKY_DATAFLOW_1,                                      // nested loops with tricky data flow
183                 LOOPCASE_NESTED_TRICKY_DATAFLOW_2,                                      // nested loops with tricky data flow
184
185                 //LOOPCASE_MULTI_DECLARATION,                                           // for (int i,j,k; ...) ...  -- illegal?
186
187                 LOOPCASE_LAST
188 };
189
190 static const char* getLoopCaseName (LoopCase loopCase)
191 {
192                 static const char* s_names[] =
193                 {
194                                 "empty_body",
195                                 "infinite_with_unconditional_break_first",
196                                 "infinite_with_unconditional_break_last",
197                                 "infinite_with_conditional_break",
198                                 "single_statement",
199                                 "compound_statement",
200                                 "sequence_statement",
201                                 "no_iterations",
202                                 "single_iteration",
203                                 "select_iteration_count",
204                                 "conditional_continue",
205                                 "unconditional_continue",
206                                 "only_continue",
207                                 "double_continue",
208                                 "conditional_break",
209                                 "unconditional_break",
210                                 "pre_increment",
211                                 "post_increment",
212                                 "mixed_break_continue",
213                                 "vector_counter",
214                                 "101_iterations",
215                                 "sequence",
216                                 "nested",
217                                 "nested_sequence",
218                                 "nested_tricky_dataflow_1",
219                                 "nested_tricky_dataflow_2"
220                                 //"multi_declaration",
221                 };
222
223                 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPCASE_LAST);
224                 DE_ASSERT(deInBounds32((int)loopCase, 0, LOOPCASE_LAST));
225                 return s_names[(int)loopCase];
226 }
227
228 static const char* getLoopCountTypeName (LoopCountType countType)
229 {
230         static const char* s_names[] =
231         {
232                 "constant",
233                 "uniform",
234                 "dynamic"
235         };
236
237         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPCOUNT_LAST);
238         DE_ASSERT(deInBounds32((int)countType, 0, LOOPCOUNT_LAST));
239         return s_names[(int)countType];
240 }
241
242 static void evalLoop0Iters      (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(0,1,2); }
243 static void evalLoop1Iters      (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(1,2,3); }
244 static void evalLoop2Iters      (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(2,3,0); }
245 static void evalLoop3Iters      (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(3,0,1); }
246
247 static ShaderEvalFunc getLoopEvalFunc (int numIters)
248 {
249         switch (numIters % 4)
250         {
251                 case 0: return evalLoop0Iters;
252                 case 1: return evalLoop1Iters;
253                 case 2: return evalLoop2Iters;
254                 case 3: return evalLoop3Iters;
255         }
256
257         DE_FATAL("Invalid loop iteration count.");
258         return NULL;
259 }
260
261 // ShaderLoop case
262
263 class ShaderLoopCase : public ShaderRenderCase
264 {
265 public:
266         ShaderLoopCase  (tcu::TestContext&      testCtx,
267                                          const std::string&     name,
268                                          const std::string&     description,
269                                          bool                           isVertexCase,
270                                          ShaderEvalFunc         evalFunc,
271                                          UniformSetup*          uniformSetup,
272                                          const std::string&     vertexShaderSource,
273                                          const std::string&     fragmentShaderSource)
274                 : ShaderRenderCase              (testCtx, name, description, isVertexCase, evalFunc, uniformSetup, DE_NULL)
275         {
276                 m_vertShaderSource = vertexShaderSource;
277                 m_fragShaderSource = fragmentShaderSource;
278         }
279 };
280
281 // Uniform setup tools
282
283 class LoopUniformSetup : public UniformSetup
284 {
285 public:
286                                                                         LoopUniformSetup        (std::vector<BaseUniformType>& types)
287                                                                                 : m_uniformInformations(types)
288                                                                         {}
289
290         virtual void                                    setup                           (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const;
291
292 private:
293         std::vector<BaseUniformType>    m_uniformInformations;
294 };
295
296 void LoopUniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4&) const
297 {
298         for (size_t i = 0; i < m_uniformInformations.size(); i++)
299         {
300                 instance.useUniform((deUint32)i, m_uniformInformations[i]);
301         }
302 }
303
304 // Testcase builders
305
306 static de::MovePtr<ShaderLoopCase> createGenericLoopCase (tcu::TestContext&     testCtx,
307                                                                                                                 const std::string&      caseName,
308                                                                                                                 const std::string&      description,
309                                                                                                                 bool                            isVertexCase,
310                                                                                                                 LoopType                        loopType,
311                                                                                                                 LoopCountType           loopCountType,
312                                                                                                                 glu::Precision          loopCountPrecision,
313                                                                                                                 glu::DataType           loopCountDataType)
314 {
315         std::ostringstream vtx;
316         std::ostringstream frag;
317         std::ostringstream& op = isVertexCase ? vtx : frag;
318
319         vtx << "#version 310 es\n";
320         frag << "#version 310 es\n";
321
322         vtx << "layout(location=0) in highp vec4 a_position;\n";
323         vtx << "layout(location=1) in highp vec4 a_coords;\n";
324         frag << "layout(location=0) out mediump vec4 o_color;\n";
325
326         if (loopCountType == LOOPCOUNT_DYNAMIC)
327                 vtx << "layout(location=3) in mediump float a_one;\n";
328
329         if (isVertexCase)
330         {
331                 vtx << "layout(location=0) out mediump vec3 v_color;\n";
332                 frag << "layout(location=0) in mediump vec3 v_color;\n";
333         }
334         else
335         {
336                 vtx << "layout(location=0) out mediump vec4 v_coords;\n";
337                 frag << "layout(location=0) in mediump vec4 v_coords;\n";
338
339                 if (loopCountType == LOOPCOUNT_DYNAMIC)
340                 {
341                         vtx << "layout(location=1) out mediump float v_one;\n";
342                         frag << "layout(location=1) in mediump float v_one;\n";
343                 }
344         }
345
346         const int       numLoopIters = 3;
347         const bool      isIntCounter = isDataTypeIntOrIVec(loopCountDataType);
348         deUint32        locationCounter = 0;
349         std::vector<BaseUniformType> uniformInformations;
350
351         if (isIntCounter)
352         {
353                 if (loopCountType == LOOPCOUNT_UNIFORM || loopCountType == LOOPCOUNT_DYNAMIC)
354                 {
355                         op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff"<< locationCounter <<" {\n";
356                         op << " ${COUNTER_PRECISION} int " << getIntUniformName(numLoopIters) << ";\n";
357                         op << "};\n";
358                         uniformInformations.push_back(getIntUniformType(numLoopIters));
359                         locationCounter++;
360                 }
361         }
362         else
363         {
364                 if (loopCountType == LOOPCOUNT_UNIFORM || loopCountType == LOOPCOUNT_DYNAMIC){
365                         op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
366                         op << " ${COUNTER_PRECISION} float " << getFloatFractionUniformName(numLoopIters) << ";\n";
367                         op << "};\n";
368                         uniformInformations.push_back(getFloatFractionUniformType(numLoopIters));
369                         locationCounter++;
370                 }
371
372                 if (numLoopIters != 1){
373                         op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
374                         op << " ${COUNTER_PRECISION} float uf_one;\n";
375                         op << "};\n";
376                         uniformInformations.push_back(UF_ONE);
377                         locationCounter++;
378                 }
379         }
380
381         vtx << "\n";
382         vtx << "void main()\n";
383         vtx << "{\n";
384         vtx << "        gl_Position = a_position;\n";
385
386         frag << "\n";
387         frag << "void main()\n";
388         frag << "{\n";
389
390         if (isVertexCase)
391                 vtx << "        ${PRECISION} vec4 coords = a_coords;\n";
392         else
393                 frag << "       ${PRECISION} vec4 coords = v_coords;\n";
394
395
396         if (loopCountType == LOOPCOUNT_DYNAMIC)
397         {
398                 if (isIntCounter)
399                 {
400                         if (isVertexCase)
401                                 vtx << "        ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n";
402                         else
403                                 frag << "       ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n";
404                 }
405                 else
406                 {
407                         if (isVertexCase)
408                                 vtx << "        ${COUNTER_PRECISION} float one = a_one;\n";
409                         else
410                                 frag << "       ${COUNTER_PRECISION} float one = v_one;\n";
411                 }
412         }
413
414         // Read array.
415         op << " ${PRECISION} vec4 res = coords;\n";
416
417         // Loop iteration count.
418         std::string     iterMaxStr;
419
420         if (isIntCounter)
421         {
422                 if (loopCountType == LOOPCOUNT_CONSTANT)
423                         iterMaxStr = de::toString(numLoopIters);
424                 else if (loopCountType == LOOPCOUNT_UNIFORM)
425                         iterMaxStr = getIntUniformName(numLoopIters);
426                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
427                         iterMaxStr = std::string(getIntUniformName(numLoopIters)) + "*one";
428                 else
429                         DE_ASSERT(false);
430         }
431         else
432         {
433                 if (loopCountType == LOOPCOUNT_CONSTANT)
434                         iterMaxStr = "1.0";
435                 else if (loopCountType == LOOPCOUNT_UNIFORM)
436                         iterMaxStr = "uf_one";
437                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
438                         iterMaxStr = "uf_one*one";
439                 else
440                         DE_ASSERT(false);
441         }
442
443         // Loop operations.
444         std::string initValue                   = isIntCounter ? "0" : "0.05";
445         std::string loopCountDeclStr    = "${COUNTER_PRECISION} ${LOOP_VAR_TYPE} ndx = " + initValue;
446         std::string loopCmpStr                  = ("ndx < " + iterMaxStr);
447         std::string incrementStr;
448         if (isIntCounter)
449                 incrementStr = "ndx++";
450         else
451         {
452                 if (loopCountType == LOOPCOUNT_CONSTANT)
453                         incrementStr = std::string("ndx += ") + de::toString(1.0f / (float)numLoopIters);
454                 else if (loopCountType == LOOPCOUNT_UNIFORM)
455                         incrementStr = std::string("ndx += ") + getFloatFractionUniformName(numLoopIters);
456                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
457                         incrementStr = std::string("ndx += ") + getFloatFractionUniformName(numLoopIters) + "*one";
458                 else
459                         DE_ASSERT(false);
460         }
461
462         // Loop body.
463         std::string loopBody;
464
465         loopBody = "            res = res.yzwx;\n";
466
467         if (loopType == LOOPTYPE_FOR)
468         {
469                 op << " for (" + loopCountDeclStr + "; " + loopCmpStr + "; " + incrementStr + ")\n";
470                 op << " {\n";
471                 op << loopBody;
472                 op << " }\n";
473         }
474         else if (loopType == LOOPTYPE_WHILE)
475         {
476                 op << "\t" << loopCountDeclStr + ";\n";
477                 op << " while (" + loopCmpStr + ")\n";
478                 op << " {\n";
479                 op << loopBody;
480                 op << "\t\t" + incrementStr + ";\n";
481                 op << " }\n";
482         }
483         else if (loopType == LOOPTYPE_DO_WHILE)
484         {
485                 op << "\t" << loopCountDeclStr + ";\n";
486                 op << " do\n";
487                 op << " {\n";
488                 op << loopBody;
489                 op << "\t\t" + incrementStr + ";\n";
490                 op << " } while (" + loopCmpStr + ");\n";
491         }
492         else
493                 DE_ASSERT(false);
494
495         if (isVertexCase)
496         {
497                 vtx << "        v_color = res.rgb;\n";
498                 frag << "       o_color = vec4(v_color.rgb, 1.0);\n";
499         }
500         else
501         {
502                 vtx << "        v_coords = a_coords;\n";
503                 frag << "       o_color = vec4(res.rgb, 1.0);\n";
504
505                 if (loopCountType == LOOPCOUNT_DYNAMIC)
506                         vtx << "        v_one = a_one;\n";
507         }
508
509         vtx << "}\n";
510         frag << "}\n";
511
512         // Fill in shader templates.
513         std::map<std::string, std::string> params;
514         params.insert(std::pair<std::string, std::string>("LOOP_VAR_TYPE", getDataTypeName(loopCountDataType)));
515         params.insert(std::pair<std::string, std::string>("PRECISION", "mediump"));
516         params.insert(std::pair<std::string, std::string>("COUNTER_PRECISION", getPrecisionName(loopCountPrecision)));
517
518         tcu::StringTemplate vertTemplate(vtx.str());
519         tcu::StringTemplate fragTemplate(frag.str());
520         std::string vertexShaderSource = vertTemplate.specialize(params);
521         std::string fragmentShaderSource = fragTemplate.specialize(params);
522
523         // Create the case.
524         ShaderEvalFunc evalFunc = getLoopEvalFunc(numLoopIters);
525         UniformSetup* uniformSetup = new LoopUniformSetup(uniformInformations);
526         return de::MovePtr<ShaderLoopCase>(new ShaderLoopCase(testCtx, caseName, description, isVertexCase, evalFunc, uniformSetup, vertexShaderSource, fragmentShaderSource));
527 }
528
529 static de::MovePtr<ShaderLoopCase> createSpecialLoopCase (tcu::TestContext&     testCtx,
530                                                                                                                 const std::string&      caseName,
531                                                                                                                 const std::string&      description,
532                                                                                                                 bool                            isVertexCase,
533                                                                                                                 LoopCase                        loopCase,
534                                                                                                                 LoopType                        loopType,
535                                                                                                                 LoopCountType           loopCountType)
536 {
537         std::ostringstream vtx;
538         std::ostringstream frag;
539         std::ostringstream& op = isVertexCase ? vtx : frag;
540
541         std::vector<BaseUniformType>    uniformInformations;
542         deUint32                                                locationCounter = 0;
543
544         vtx << "#version 310 es\n";
545         frag << "#version 310 es\n";
546
547         vtx << "layout(location=0) in highp vec4 a_position;\n";
548         vtx << "layout(location=1) in highp vec4 a_coords;\n";
549         frag << "layout(location=0) out mediump vec4 o_color;\n";
550
551         if (loopCountType == LOOPCOUNT_DYNAMIC)
552                 vtx << "layout(location=3) in mediump float a_one;\n";
553
554         if (isVertexCase)
555         {
556                 vtx << "layout(location=0) out mediump vec3 v_color;\n";
557                 frag << "layout(location=0) in mediump vec3 v_color;\n";
558         }
559         else
560         {
561                 vtx << "layout(location=0) out mediump vec4 v_coords;\n";
562                 frag << "layout(location=0) in mediump vec4 v_coords;\n";
563
564                 if (loopCountType == LOOPCOUNT_DYNAMIC)
565                 {
566                         vtx << "layout(location=1) out mediump float v_one;\n";
567                         frag << "layout(location=1) in mediump float v_one;\n";
568                 }
569         }
570
571         if (loopCase == LOOPCASE_SELECT_ITERATION_COUNT) {
572                 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
573                 op << "  bool ub_true;\n";
574                 op << "};\n";
575                 uniformInformations.push_back(UB_TRUE);
576                 locationCounter++;
577         }
578
579         struct
580         {
581                 char const*             name;
582                 BaseUniformType type;
583         } uniforms[] =
584         {
585                 { "ui_zero",    UI_ZERO },
586                 { "ui_one",             UI_ONE },
587                 { "ui_two",             UI_TWO },
588                 { "ui_three",   UI_THREE },
589                 { "ui_four",    UI_FOUR },
590                 { "ui_five",    UI_FIVE },
591                 { "ui_six",             UI_SIX  },
592         };
593
594         for (int i = 0; i < DE_LENGTH_OF_ARRAY(uniforms); ++i)
595         {
596                 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
597                 op << "  ${COUNTER_PRECISION} int " << uniforms[i].name << ";\n";
598                 op << "};\n";
599                 uniformInformations.push_back(uniforms[i].type);
600                 locationCounter++;
601         }
602
603         if (loopCase == LOOPCASE_101_ITERATIONS) {
604
605                 op << "layout(std140, set=0, binding=" << locationCounter <<  ") uniform buff" << locationCounter << " {\n";
606                 op << "  ${COUNTER_PRECISION} int ui_oneHundredOne;\n";
607                 op << "};\n";
608                 uniformInformations.push_back(UI_ONEHUNDREDONE);
609                 locationCounter++;
610         }
611
612         int iterCount   = 3;    // value to use in loop
613         int numIters    = 3;    // actual number of iterations
614
615         vtx << "\n";
616         vtx << "void main()\n";
617         vtx << "{\n";
618         vtx << "        gl_Position = a_position;\n";
619
620         frag << "\n";
621         frag << "void main()\n";
622         frag << "{\n";
623
624         if (loopCountType == LOOPCOUNT_DYNAMIC)
625         {
626                 if (isVertexCase)
627                         vtx << "        ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n";
628                 else
629                         frag << "       ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n";
630         }
631
632         if (isVertexCase)
633                 vtx << "        ${PRECISION} vec4 coords = a_coords;\n";
634         else
635                 frag << "       ${PRECISION} vec4 coords = v_coords;\n";
636
637         // Read array.
638         op << " ${PRECISION} vec4 res = coords;\n";
639
640         // Handle all loop types.
641         std::string counterPrecisionStr = "mediump";
642         std::string forLoopStr;
643         std::string whileLoopStr;
644         std::string doWhileLoopPreStr;
645         std::string doWhileLoopPostStr;
646
647         if (loopType == LOOPTYPE_FOR)
648         {
649                 switch (loopCase)
650                 {
651                         case LOOPCASE_EMPTY_BODY:
652                                 numIters = 0;
653                                 op << " ${FOR_LOOP} {}\n";
654                                 break;
655
656                         case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
657                                 numIters = 0;
658                                 op << " for (;;) { break; res = res.yzwx; }\n";
659                                 break;
660
661                         case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
662                                 numIters = 1;
663                                 op << " for (;;) { res = res.yzwx; break; }\n";
664                                 break;
665
666                         case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
667                                 numIters = 2;
668                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
669                                 op << " for (;;) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n";
670                                 break;
671
672                         case LOOPCASE_SINGLE_STATEMENT:
673                                 op << " ${FOR_LOOP} res = res.yzwx;\n";
674                                 break;
675
676                         case LOOPCASE_COMPOUND_STATEMENT:
677                                 iterCount       = 2;
678                                 numIters        = 2 * iterCount;
679                                 op << " ${FOR_LOOP} { res = res.yzwx; res = res.yzwx; }\n";
680                                 break;
681
682                         case LOOPCASE_SEQUENCE_STATEMENT:
683                                 iterCount       = 2;
684                                 numIters        = 2 * iterCount;
685                                 op << " ${FOR_LOOP} res = res.yzwx, res = res.yzwx;\n";
686                                 break;
687
688                         case LOOPCASE_NO_ITERATIONS:
689                                 iterCount       = 0;
690                                 numIters        = 0;
691                                 op << " ${FOR_LOOP} res = res.yzwx;\n";
692                                 break;
693
694                         case LOOPCASE_SINGLE_ITERATION:
695                                 iterCount       = 1;
696                                 numIters        = 1;
697                                 op << " ${FOR_LOOP} res = res.yzwx;\n";
698                                 break;
699
700                         case LOOPCASE_SELECT_ITERATION_COUNT:
701                                 op << " for (int i = 0; i < (ub_true ? ${ITER_COUNT} : 0); i++) res = res.yzwx;\n";
702                                 break;
703
704                         case LOOPCASE_CONDITIONAL_CONTINUE:
705                                 numIters = iterCount - 1;
706                                 op << " ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n";
707                                 break;
708
709                         case LOOPCASE_UNCONDITIONAL_CONTINUE:
710                                 op << " ${FOR_LOOP} { res = res.yzwx; continue; }\n";
711                                 break;
712
713                         case LOOPCASE_ONLY_CONTINUE:
714                                 numIters = 0;
715                                 op << " ${FOR_LOOP} { continue; }\n";
716                                 break;
717
718                         case LOOPCASE_DOUBLE_CONTINUE:
719                                 numIters = iterCount - 1;
720                                 op << " ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; continue; }\n";
721                                 break;
722
723                         case LOOPCASE_CONDITIONAL_BREAK:
724                                 numIters = 2;
725                                 op << " ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx; }\n";
726                                 break;
727
728                         case LOOPCASE_UNCONDITIONAL_BREAK:
729                                 numIters = 1;
730                                 op << " ${FOR_LOOP} { res = res.yzwx; break; }\n";
731                                 break;
732
733                         case LOOPCASE_PRE_INCREMENT:
734                                 op << " for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx; }\n";
735                                 break;
736
737                         case LOOPCASE_POST_INCREMENT:
738                                 op << " ${FOR_LOOP} { res = res.yzwx; }\n";
739                                 break;
740
741                         case LOOPCASE_MIXED_BREAK_CONTINUE:
742                                 numIters        = 2;
743                                 iterCount       = 5;
744                                 op << " ${FOR_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n";
745                                 break;
746
747                         case LOOPCASE_VECTOR_COUNTER:
748                                 op << " for (${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0); i.x < i.z; i.x += i.y) { res = res.yzwx; }\n";
749                                 break;
750
751                         case LOOPCASE_101_ITERATIONS:
752                                 numIters = iterCount = 101;
753                                 op << " ${FOR_LOOP} res = res.yzwx;\n";
754                                 break;
755
756                         case LOOPCASE_SEQUENCE:
757                                 iterCount       = 5;
758                                 numIters        = 5;
759                                 op << " ${COUNTER_PRECISION} int i;\n";
760                                 op << " for (i = 0; i < ${TWO}; i++) { res = res.yzwx; }\n";
761                                 op << " for (; i < ${ITER_COUNT}; i++) { res = res.yzwx; }\n";
762                                 break;
763
764                         case LOOPCASE_NESTED:
765                                 numIters = 2 * iterCount;
766                                 op << " for (${COUNTER_PRECISION} int i = 0; i < ${TWO}; i++)\n";
767                                 op << " {\n";
768                                 op << "         for (${COUNTER_PRECISION} int j = 0; j < ${ITER_COUNT}; j++)\n";
769                                 op << "                 res = res.yzwx;\n";
770                                 op << " }\n";
771                                 break;
772
773                         case LOOPCASE_NESTED_SEQUENCE:
774                                 numIters = 3 * iterCount;
775                                 op << " for (${COUNTER_PRECISION} int i = 0; i < ${ITER_COUNT}; i++)\n";
776                                 op << " {\n";
777                                 op << "         for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
778                                 op << "                 res = res.yzwx;\n";
779                                 op << "         for (${COUNTER_PRECISION} int j = 0; j < ${ONE}; j++)\n";
780                                 op << "                 res = res.yzwx;\n";
781                                 op << " }\n";
782                                 break;
783
784                         case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
785                                 numIters = 2;
786                                 op << " ${FOR_LOOP}\n";
787                                 op << " {\n";
788                                 op << "         res = coords; // ignore outer loop effect \n";
789                                 op << "         for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
790                                 op << "                 res = res.yzwx;\n";
791                                 op << " }\n";
792                                 break;
793
794                         case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
795                                 numIters = iterCount;
796                                 op << " ${FOR_LOOP}\n";
797                                 op << " {\n";
798                                 op << "         res = coords.wxyz;\n";
799                                 op << "         for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
800                                 op << "                 res = res.yzwx;\n";
801                                 op << "         coords = res;\n";
802                                 op << " }\n";
803                                 break;
804
805                         default:
806                                 DE_ASSERT(false);
807                 }
808
809                 if (loopCountType == LOOPCOUNT_CONSTANT)
810                         forLoopStr = std::string("for (") + counterPrecisionStr + " int i = 0; i < " + de::toString(iterCount) + "; i++)";
811                 else if (loopCountType == LOOPCOUNT_UNIFORM)
812                         forLoopStr = std::string("for (") + counterPrecisionStr + " int i = 0; i < " + getIntUniformName(iterCount) + "; i++)";
813                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
814                         forLoopStr = std::string("for (") + counterPrecisionStr + " int i = 0; i < one*" + getIntUniformName(iterCount) + "; i++)";
815                 else
816                         DE_ASSERT(false);
817         }
818         else if (loopType == LOOPTYPE_WHILE)
819         {
820                 switch (loopCase)
821                 {
822                         case LOOPCASE_EMPTY_BODY:
823                                 numIters = 0;
824                                 op << " ${WHILE_LOOP} {}\n";
825                                 break;
826
827                         case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
828                                 numIters = 0;
829                                 op << " while (true) { break; res = res.yzwx; }\n";
830                                 break;
831
832                         case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
833                                 numIters = 1;
834                                 op << " while (true) { res = res.yzwx; break; }\n";
835                                 break;
836
837                         case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
838                                 numIters = 2;
839                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
840                                 op << " while (true) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n";
841                                 break;
842
843                         case LOOPCASE_SINGLE_STATEMENT:
844                                 op << " ${WHILE_LOOP} res = res.yzwx;\n";
845                                 break;
846
847                         case LOOPCASE_COMPOUND_STATEMENT:
848                                 iterCount       = 2;
849                                 numIters        = 2 * iterCount;
850                                 op << " ${WHILE_LOOP} { res = res.yzwx; res = res.yzwx; }\n";
851                                 break;
852
853                         case LOOPCASE_SEQUENCE_STATEMENT:
854                                 iterCount       = 2;
855                                 numIters        = 2 * iterCount;
856                                 op << " ${WHILE_LOOP} res = res.yzwx, res = res.yzwx;\n";
857                                 break;
858
859                         case LOOPCASE_NO_ITERATIONS:
860                                 iterCount       = 0;
861                                 numIters        = 0;
862                                 op << " ${WHILE_LOOP} res = res.yzwx;\n";
863                                 break;
864
865                         case LOOPCASE_SINGLE_ITERATION:
866                                 iterCount       = 1;
867                                 numIters        = 1;
868                                 op << " ${WHILE_LOOP} res = res.yzwx;\n";
869                                 break;
870
871                         case LOOPCASE_SELECT_ITERATION_COUNT:
872                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
873                                 op << " while (i < (ub_true ? ${ITER_COUNT} : 0)) { res = res.yzwx; i++; }\n";
874                                 break;
875
876                         case LOOPCASE_CONDITIONAL_CONTINUE:
877                                 numIters = iterCount - 1;
878                                 op << " ${WHILE_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n";
879                                 break;
880
881                         case LOOPCASE_UNCONDITIONAL_CONTINUE:
882                                 op << " ${WHILE_LOOP} { res = res.yzwx; continue; }\n";
883                                 break;
884
885                         case LOOPCASE_ONLY_CONTINUE:
886                                 numIters = 0;
887                                 op << " ${WHILE_LOOP} { continue; }\n";
888                                 break;
889
890                         case LOOPCASE_DOUBLE_CONTINUE:
891                                 numIters = iterCount - 1;
892                                 op << " ${WHILE_LOOP} { if (i == ${ONE}) continue; res = res.yzwx; continue; }\n";
893                                 break;
894
895                         case LOOPCASE_CONDITIONAL_BREAK:
896                                 numIters = 2;
897                                 op << " ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx; }\n";
898                                 break;
899
900                         case LOOPCASE_UNCONDITIONAL_BREAK:
901                                 numIters = 1;
902                                 op << " ${WHILE_LOOP} { res = res.yzwx; break; }\n";
903                                 break;
904
905                         case LOOPCASE_PRE_INCREMENT:
906                                 numIters = iterCount - 1;
907                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
908                                 op << " while (++i < ${ITER_COUNT}) { res = res.yzwx; }\n";
909                                 break;
910
911                         case LOOPCASE_POST_INCREMENT:
912                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
913                                 op << " while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n";
914                                 break;
915
916                         case LOOPCASE_MIXED_BREAK_CONTINUE:
917                                 numIters        = 2;
918                                 iterCount       = 5;
919                                 op << " ${WHILE_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n";
920                                 break;
921
922                         case LOOPCASE_VECTOR_COUNTER:
923                                 op << " ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n";
924                                 op << " while (i.x < i.z) { res = res.yzwx; i.x += i.y; }\n";
925                                 break;
926
927                         case LOOPCASE_101_ITERATIONS:
928                                 numIters = iterCount = 101;
929                                 op << " ${WHILE_LOOP} res = res.yzwx;\n";
930                                 break;
931
932                         case LOOPCASE_SEQUENCE:
933                                 iterCount       = 6;
934                                 numIters        = iterCount - 1;
935                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
936                                 op << " while (i++ < ${TWO}) { res = res.yzwx; }\n";
937                                 op << " while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n"; // \note skips one iteration
938                                 break;
939
940                         case LOOPCASE_NESTED:
941                                 numIters = 2 * iterCount;
942                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
943                                 op << " while (i++ < ${TWO})\n";
944                                 op << " {\n";
945                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
946                                 op << "         while (j++ < ${ITER_COUNT})\n";
947                                 op << "                 res = res.yzwx;\n";
948                                 op << " }\n";
949                                 break;
950
951                         case LOOPCASE_NESTED_SEQUENCE:
952                                 numIters = 2 * iterCount;
953                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
954                                 op << " while (i++ < ${ITER_COUNT})\n";
955                                 op << " {\n";
956                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
957                                 op << "         while (j++ < ${ONE})\n";
958                                 op << "                 res = res.yzwx;\n";
959                                 op << "         while (j++ < ${THREE})\n"; // \note skips one iteration
960                                 op << "                 res = res.yzwx;\n";
961                                 op << " }\n";
962                                 break;
963
964                         case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
965                                 numIters = 2;
966                                 op << " ${WHILE_LOOP}\n";
967                                 op << " {\n";
968                                 op << "         res = coords; // ignore outer loop effect \n";
969                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
970                                 op << "         while (j++ < ${TWO})\n";
971                                 op << "                 res = res.yzwx;\n";
972                                 op << " }\n";
973                                 break;
974
975                         case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
976                                 numIters = iterCount;
977                                 op << " ${WHILE_LOOP}\n";
978                                 op << " {\n";
979                                 op << "         res = coords.wxyz;\n";
980                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
981                                 op << "         while (j++ < ${TWO})\n";
982                                 op << "                 res = res.yzwx;\n";
983                                 op << "         coords = res;\n";
984                                 op << " }\n";
985                                 break;
986
987                         default:
988                                 DE_ASSERT(false);
989                 }
990
991                 if (loopCountType == LOOPCOUNT_CONSTANT)
992                         whileLoopStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + "    while(i++ < " + de::toString(iterCount) + ")";
993                 else if (loopCountType == LOOPCOUNT_UNIFORM)
994                         whileLoopStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + "    while(i++ < " + getIntUniformName(iterCount) + ")";
995                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
996                         whileLoopStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + "    while(i++ < one*" + getIntUniformName(iterCount) + ")";
997                 else
998                         DE_ASSERT(false);
999         }
1000         else
1001         {
1002                 DE_ASSERT(loopType == LOOPTYPE_DO_WHILE);
1003
1004                 switch (loopCase)
1005                 {
1006                         case LOOPCASE_EMPTY_BODY:
1007                                 numIters = 0;
1008                                 op << " ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n";
1009                                 break;
1010
1011                         case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
1012                                 numIters = 0;
1013                                 op << " do { break; res = res.yzwx; } while (true);\n";
1014                                 break;
1015
1016                         case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
1017                                 numIters = 1;
1018                                 op << " do { res = res.yzwx; break; } while (true);\n";
1019                                 break;
1020
1021                         case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
1022                                 numIters = 2;
1023                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1024                                 op << " do { res = res.yzwx; if (i == ${ONE}) break; i++; } while (true);\n";
1025                                 break;
1026
1027                         case LOOPCASE_SINGLE_STATEMENT:
1028                                 op << " ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n";
1029                                 break;
1030
1031                         case LOOPCASE_COMPOUND_STATEMENT:
1032                                 iterCount       = 2;
1033                                 numIters        = 2 * iterCount;
1034                                 op << " ${DO_WHILE_PRE} { res = res.yzwx; res = res.yzwx; } ${DO_WHILE_POST}\n";
1035                                 break;
1036
1037                         case LOOPCASE_SEQUENCE_STATEMENT:
1038                                 iterCount       = 2;
1039                                 numIters        = 2 * iterCount;
1040                                 op << " ${DO_WHILE_PRE} res = res.yzwx, res = res.yzwx; ${DO_WHILE_POST}\n";
1041                                 break;
1042
1043                         case LOOPCASE_NO_ITERATIONS:
1044                                 DE_ASSERT(false);
1045                                 break;
1046
1047                         case LOOPCASE_SINGLE_ITERATION:
1048                                 iterCount       = 1;
1049                                 numIters        = 1;
1050                                 op << " ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n";
1051                                 break;
1052
1053                         case LOOPCASE_SELECT_ITERATION_COUNT:
1054                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1055                                 op << " do { res = res.yzwx; } while (++i < (ub_true ? ${ITER_COUNT} : 0));\n";
1056                                 break;
1057
1058                         case LOOPCASE_CONDITIONAL_CONTINUE:
1059                                 numIters = iterCount - 1;
1060                                 op << " ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; } ${DO_WHILE_POST}\n";
1061                                 break;
1062
1063                         case LOOPCASE_UNCONDITIONAL_CONTINUE:
1064                                 op << " ${DO_WHILE_PRE} { res = res.yzwx; continue; } ${DO_WHILE_POST}\n";
1065                                 break;
1066
1067                         case LOOPCASE_ONLY_CONTINUE:
1068                                 numIters = 0;
1069                                 op << " ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n";
1070                                 break;
1071
1072                         case LOOPCASE_DOUBLE_CONTINUE:
1073                                 numIters = iterCount - 1;
1074                                 op << " ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; continue; } ${DO_WHILE_POST}\n";
1075                                 break;
1076
1077                         case LOOPCASE_CONDITIONAL_BREAK:
1078                                 numIters = 2;
1079                                 op << " ${DO_WHILE_PRE} { res = res.yzwx; if (i == ${ONE}) break; } ${DO_WHILE_POST}\n";
1080                                 break;
1081
1082                         case LOOPCASE_UNCONDITIONAL_BREAK:
1083                                 numIters = 1;
1084                                 op << " ${DO_WHILE_PRE} { res = res.yzwx; break; } ${DO_WHILE_POST}\n";
1085                                 break;
1086
1087                         case LOOPCASE_PRE_INCREMENT:
1088                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1089                                 op << " do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n";
1090                                 break;
1091
1092                         case LOOPCASE_POST_INCREMENT:
1093                                 numIters = iterCount + 1;
1094                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1095                                 op << " do { res = res.yzwx; } while (i++ < ${ITER_COUNT});\n";
1096                                 break;
1097
1098                         case LOOPCASE_MIXED_BREAK_CONTINUE:
1099                                 numIters        = 2;
1100                                 iterCount       = 5;
1101                                 op << " ${DO_WHILE_PRE} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; } ${DO_WHILE_POST}\n";
1102                                 break;
1103
1104                         case LOOPCASE_VECTOR_COUNTER:
1105                                 op << " ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n";
1106                                 op << " do { res = res.yzwx; } while ((i.x += i.y) < i.z);\n";
1107                                 break;
1108
1109                         case LOOPCASE_101_ITERATIONS:
1110                                 numIters = iterCount = 101;
1111                                 op << " ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n";
1112                                 break;
1113
1114                         case LOOPCASE_SEQUENCE:
1115                                 iterCount       = 5;
1116                                 numIters        = 5;
1117                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1118                                 op << " do { res = res.yzwx; } while (++i < ${TWO});\n";
1119                                 op << " do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n";
1120                                 break;
1121
1122                         case LOOPCASE_NESTED:
1123                                 numIters = 2 * iterCount;
1124                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1125                                 op << " do\n";
1126                                 op << " {\n";
1127                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
1128                                 op << "         do\n";
1129                                 op << "                 res = res.yzwx;\n";
1130                                 op << "         while (++j < ${ITER_COUNT});\n";
1131                                 op << " } while (++i < ${TWO});\n";
1132                                 break;
1133
1134                         case LOOPCASE_NESTED_SEQUENCE:
1135                                 numIters = 3 * iterCount;
1136                                 op << " ${COUNTER_PRECISION} int i = 0;\n";
1137                                 op << " do\n";
1138                                 op << " {\n";
1139                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
1140                                 op << "         do\n";
1141                                 op << "                 res = res.yzwx;\n";
1142                                 op << "         while (++j < ${TWO});\n";
1143                                 op << "         do\n";
1144                                 op << "                 res = res.yzwx;\n";
1145                                 op << "         while (++j < ${THREE});\n";
1146                                 op << " } while (++i < ${ITER_COUNT});\n";
1147                                 break;
1148
1149                         case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
1150                                 numIters = 2;
1151                                 op << " ${DO_WHILE_PRE}\n";
1152                                 op << " {\n";
1153                                 op << "         res = coords; // ignore outer loop effect \n";
1154                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
1155                                 op << "         do\n";
1156                                 op << "                 res = res.yzwx;\n";
1157                                 op << "         while (++j < ${TWO});\n";
1158                                 op << " } ${DO_WHILE_POST}\n";
1159                                 break;
1160
1161                         case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
1162                                 numIters = iterCount;
1163                                 op << " ${DO_WHILE_PRE}\n";
1164                                 op << " {\n";
1165                                 op << "         res = coords.wxyz;\n";
1166                                 op << "         ${COUNTER_PRECISION} int j = 0;\n";
1167                                 op << "         while (j++ < ${TWO})\n";
1168                                 op << "                 res = res.yzwx;\n";
1169                                 op << "         coords = res;\n";
1170                                 op << " } ${DO_WHILE_POST}\n";
1171                                 break;
1172
1173                         default:
1174                                 DE_ASSERT(false);
1175                 }
1176
1177                 doWhileLoopPreStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + "\tdo ";
1178                 if (loopCountType == LOOPCOUNT_CONSTANT)
1179                         doWhileLoopPostStr = std::string(" while (++i < ") + de::toString(iterCount) + ");\n";
1180                 else if (loopCountType == LOOPCOUNT_UNIFORM)
1181                         doWhileLoopPostStr = std::string(" while (++i < ") + getIntUniformName(iterCount) + ");\n";
1182                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
1183                         doWhileLoopPostStr = std::string(" while (++i < one*") + getIntUniformName(iterCount) + ");\n";
1184                 else
1185                         DE_ASSERT(false);
1186         }
1187
1188         // Shader footers.
1189         if (isVertexCase)
1190         {
1191                 vtx << "        v_color = res.rgb;\n";
1192                 frag << "       o_color = vec4(v_color.rgb, 1.0);\n";
1193         }
1194         else
1195         {
1196                 vtx << "        v_coords = a_coords;\n";
1197                 frag << "       o_color = vec4(res.rgb, 1.0);\n";
1198
1199                 if (loopCountType == LOOPCOUNT_DYNAMIC)
1200                         vtx << "        v_one = a_one;\n";
1201         }
1202
1203         vtx << "}\n";
1204         frag << "}\n";
1205
1206         // Constants.
1207         std::string oneStr;
1208         std::string twoStr;
1209         std::string threeStr;
1210         std::string iterCountStr;
1211
1212         if (loopCountType == LOOPCOUNT_CONSTANT)
1213         {
1214                 oneStr                  = "1";
1215                 twoStr                  = "2";
1216                 threeStr                = "3";
1217                 iterCountStr    = de::toString(iterCount);
1218         }
1219         else if (loopCountType == LOOPCOUNT_UNIFORM)
1220         {
1221                 oneStr                  = "ui_one";
1222                 twoStr                  = "ui_two";
1223                 threeStr                = "ui_three";
1224                 iterCountStr    = getIntUniformName(iterCount);
1225         }
1226         else if (loopCountType == LOOPCOUNT_DYNAMIC)
1227         {
1228                 oneStr                  = "one*ui_one";
1229                 twoStr                  = "one*ui_two";
1230                 threeStr                = "one*ui_three";
1231                 iterCountStr    = std::string("one*") + getIntUniformName(iterCount);
1232         }
1233         else DE_ASSERT(false);
1234
1235         // Fill in shader templates.
1236         std::map<std::string, std::string> params;
1237         params.insert(std::pair<std::string, std::string>("PRECISION", "mediump"));
1238         params.insert(std::pair<std::string, std::string>("ITER_COUNT", iterCountStr));
1239         params.insert(std::pair<std::string, std::string>("COUNTER_PRECISION", counterPrecisionStr));
1240         params.insert(std::pair<std::string, std::string>("FOR_LOOP", forLoopStr));
1241         params.insert(std::pair<std::string, std::string>("WHILE_LOOP", whileLoopStr));
1242         params.insert(std::pair<std::string, std::string>("DO_WHILE_PRE", doWhileLoopPreStr));
1243         params.insert(std::pair<std::string, std::string>("DO_WHILE_POST", doWhileLoopPostStr));
1244         params.insert(std::pair<std::string, std::string>("ONE", oneStr));
1245         params.insert(std::pair<std::string, std::string>("TWO", twoStr));
1246         params.insert(std::pair<std::string, std::string>("THREE", threeStr));
1247
1248         tcu::StringTemplate vertTemplate(vtx.str());
1249         tcu::StringTemplate fragTemplate(frag.str());
1250         std::string vertexShaderSource = vertTemplate.specialize(params);
1251         std::string fragmentShaderSource = fragTemplate.specialize(params);
1252
1253         // Create the case.
1254         UniformSetup* uniformSetup = new LoopUniformSetup(uniformInformations);
1255         ShaderEvalFunc evalFunc = getLoopEvalFunc(numIters);
1256         return de::MovePtr<ShaderLoopCase>(new ShaderLoopCase(testCtx, caseName, description, isVertexCase, evalFunc, uniformSetup, vertexShaderSource, fragmentShaderSource));
1257 }
1258
1259 class ShaderLoopTests : public tcu::TestCaseGroup
1260 {
1261 public:
1262                                                         ShaderLoopTests                 (tcu::TestContext& testCtx);
1263         virtual                                 ~ShaderLoopTests                (void);
1264
1265         virtual void                    init                                    (void);
1266
1267 private:
1268                                                         ShaderLoopTests                 (const ShaderLoopTests&);               // not allowed!
1269         ShaderLoopTests&                operator=                               (const ShaderLoopTests&);               // not allowed!
1270 };
1271
1272 ShaderLoopTests::ShaderLoopTests(tcu::TestContext& testCtx)
1273                 : TestCaseGroup(testCtx, "loops", "Loop Tests")
1274 {
1275 }
1276
1277 ShaderLoopTests::~ShaderLoopTests (void)
1278 {
1279 }
1280
1281 void ShaderLoopTests::init (void)
1282 {
1283         // Loop cases.
1284
1285         static const glu::ShaderType s_shaderTypes[] =
1286         {
1287                 glu::SHADERTYPE_VERTEX,
1288                 glu::SHADERTYPE_FRAGMENT
1289         };
1290
1291         static const glu::DataType s_countDataType[] =
1292         {
1293                 glu::TYPE_INT,
1294                 glu::TYPE_FLOAT
1295         };
1296
1297         TestCaseGroup* genericGroup = new TestCaseGroup(m_testCtx, "generic", "Generic loop tests.");
1298         TestCaseGroup* specialGroup = new TestCaseGroup(m_testCtx, "special", "Special loop tests.");
1299         addChild(genericGroup);
1300         addChild(specialGroup);
1301
1302         for (int loopType = 0; loopType < LOOPTYPE_LAST; loopType++)
1303         {
1304                 const char* loopTypeName = getLoopTypeName((LoopType)loopType);
1305
1306                 for (int loopCountType = 0; loopCountType < LOOPCOUNT_LAST; loopCountType++)
1307                 {
1308                         const char* loopCountName = getLoopCountTypeName((LoopCountType)loopCountType);
1309
1310                         std::string groupName = std::string(loopTypeName) + "_" + std::string(loopCountName) + "_iterations";
1311                         std::string groupDesc = std::string("Loop tests with ") + loopCountName + " loop counter.";
1312                         TestCaseGroup* genericSubGroup = new TestCaseGroup(m_testCtx, groupName.c_str(), groupDesc.c_str());
1313                         TestCaseGroup* specialSubGroup = new TestCaseGroup(m_testCtx, groupName.c_str(), groupDesc.c_str());
1314                         genericGroup->addChild(genericSubGroup);
1315                         specialGroup->addChild(specialSubGroup);
1316
1317                         // Generic cases.
1318
1319                         for (int precision = glu::PRECISION_MEDIUMP; precision < glu::PRECISION_LAST; precision++)
1320                         {
1321                                 const char* precisionName = getPrecisionName((glu::Precision)precision);
1322
1323                                 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_countDataType); dataTypeNdx++)
1324                                 {
1325                                         glu::DataType loopDataType = s_countDataType[dataTypeNdx];
1326                                         const char* dataTypeName = getDataTypeName(loopDataType);
1327
1328                                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1329                                         {
1330                                                 glu::ShaderType shaderType              = s_shaderTypes[shaderTypeNdx];
1331                                                 const char*     shaderTypeName  = getShaderTypeName(shaderType);
1332                                                 bool            isVertexCase    = (shaderType == glu::SHADERTYPE_VERTEX);
1333
1334                                                 std::string testName = std::string("basic_") + precisionName + "_" + dataTypeName + "_" + shaderTypeName;
1335                                                 std::string testDesc = std::string(loopTypeName) + " loop with " + precisionName + dataTypeName + " " + loopCountName + " iteration count in " + shaderTypeName + " shader.";
1336                                                 de::MovePtr<ShaderLoopCase> testCase(createGenericLoopCase(m_testCtx, testName.c_str(), testDesc.c_str(), isVertexCase, (LoopType)loopType, (LoopCountType)loopCountType, (glu::Precision)precision, loopDataType));
1337                                                 genericSubGroup->addChild(testCase.release());
1338                                         }
1339                                 }
1340                         }
1341
1342                         // Special cases.
1343
1344                         for (int loopCase = 0; loopCase < LOOPCASE_LAST; loopCase++)
1345                         {
1346                                 const char* loopCaseName = getLoopCaseName((LoopCase)loopCase);
1347
1348                                 // no-iterations not possible with do-while.
1349                                 if ((loopCase == LOOPCASE_NO_ITERATIONS) && (loopType == LOOPTYPE_DO_WHILE))
1350                                         continue;
1351
1352                                 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1353                                 {
1354                                         glu::ShaderType shaderType              = s_shaderTypes[shaderTypeNdx];
1355                                         const char*     shaderTypeName  = getShaderTypeName(shaderType);
1356                                         bool            isVertexCase    = (shaderType == glu::SHADERTYPE_VERTEX);
1357
1358                                         std::string name = std::string(loopCaseName) + "_" + shaderTypeName;
1359                                         std::string desc = std::string(loopCaseName) + " loop with " + loopTypeName + " iteration count in " + shaderTypeName + " shader.";
1360                                         de::MovePtr<ShaderLoopCase> testCase(createSpecialLoopCase(m_testCtx, name.c_str(), desc.c_str(), isVertexCase, (LoopCase)loopCase, (LoopType)loopType, (LoopCountType)loopCountType));
1361                                         specialSubGroup->addChild(testCase.release());
1362                                 }
1363                         }
1364                 }
1365         }
1366 }
1367
1368 } // anonymous
1369
1370 tcu::TestCaseGroup* createLoopTests (tcu::TestContext& testCtx)
1371 {
1372         return new ShaderLoopTests(testCtx);
1373 }
1374
1375
1376 } // sr
1377 } // vkt