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