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