Always apply flat qualifier to double inputs, same as int/uint
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcShaderLoopTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief Shader loop tests.
23  */ /*-------------------------------------------------------------------*/
24
25 #include "glcShaderLoopTests.hpp"
26 #include "glcShaderRenderCase.hpp"
27 #include "gluShaderUtil.hpp"
28 #include "tcuStringTemplate.hpp"
29
30 #include "deInt32.h"
31 #include "deMemory.h"
32 #include "deStringUtil.hpp"
33
34 #include <map>
35
36 using namespace std;
37 using namespace tcu;
38 using namespace glu;
39
40 namespace deqp
41 {
42
43 // Repeated with for, while, do-while. Examples given as 'for' loops.
44 // Repeated for const, uniform, dynamic loops.
45 enum LoopCase
46 {
47         LOOPCASE_EMPTY_BODY = 0,                                                  // for (...) { }
48         LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST, // for (...) { break; <body>; }
49         LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST,  // for (...) { <body>; break; }
50         LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK,                 // for (...) { <body>; if (cond) break; }
51         LOOPCASE_SINGLE_STATEMENT,                                                // for (...) statement;
52         LOOPCASE_COMPOUND_STATEMENT,                                      // for (...) { statement; statement; }
53         LOOPCASE_SEQUENCE_STATEMENT,                                      // for (...) statement, statement;
54         LOOPCASE_NO_ITERATIONS,                                                   // for (i=0; i<0; i++) ...
55         LOOPCASE_SINGLE_ITERATION,                                                // for (i=0; i<1; i++) ...
56         LOOPCASE_SELECT_ITERATION_COUNT,                                  // for (i=0; i<a?b:c; i++) ...
57         LOOPCASE_CONDITIONAL_CONTINUE,                                    // for (...) { if (cond) continue; }
58         LOOPCASE_UNCONDITIONAL_CONTINUE,                                  // for (...) { <body>; continue; }
59         LOOPCASE_ONLY_CONTINUE,                                                   // for (...) { continue; }
60         LOOPCASE_DOUBLE_CONTINUE,                                                 // for (...) { if (cond) continue; <body>; continue; }
61         LOOPCASE_CONDITIONAL_BREAK,                                               // for (...) { if (cond) break; }
62         LOOPCASE_UNCONDITIONAL_BREAK,                                     // for (...) { <body>; break; }
63         LOOPCASE_PRE_INCREMENT,                                                   // for (...; ++i) { <body>; }
64         LOOPCASE_POST_INCREMENT,                                                  // for (...; i++) { <body>; }
65         LOOPCASE_MIXED_BREAK_CONTINUE,
66         LOOPCASE_VECTOR_COUNTER,                   // for (ivec3 ndx = ...; ndx.x < ndx.y; ndx.x += ndx.z) { ... }
67         LOOPCASE_101_ITERATIONS,                   // loop for 101 iterations
68         LOOPCASE_SEQUENCE,                                 // two loops in sequence
69         LOOPCASE_NESTED,                                   // two nested loops
70         LOOPCASE_NESTED_SEQUENCE,                  // two loops in sequence nested inside a third
71         LOOPCASE_NESTED_TRICKY_DATAFLOW_1, // nested loops with tricky data flow
72         LOOPCASE_NESTED_TRICKY_DATAFLOW_2, // nested loops with tricky data flow
73
74         //LOOPCASE_MULTI_DECLARATION,                           // for (int i,j,k; ...) ...  -- illegal?
75
76         LOOPCASE_LAST
77 };
78
79 static const char* getLoopCaseName(LoopCase loopCase)
80 {
81         static const char* s_names[] = {
82                 "empty_body", "infinite_with_unconditional_break_first", "infinite_with_unconditional_break_last",
83                 "infinite_with_conditional_break", "single_statement", "compound_statement", "sequence_statement",
84                 "no_iterations", "single_iteration", "select_iteration_count", "conditional_continue", "unconditional_continue",
85                 "only_continue", "double_continue", "conditional_break", "unconditional_break", "pre_increment",
86                 "post_increment", "mixed_break_continue", "vector_counter", "101_iterations", "sequence", "nested",
87                 "nested_sequence", "nested_tricky_dataflow_1", "nested_tricky_dataflow_2"
88                 //"multi_declaration",
89         };
90
91         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPCASE_LAST);
92         DE_ASSERT(deInBounds32((int)loopCase, 0, LOOPCASE_LAST));
93         return s_names[(int)loopCase];
94 }
95
96 // Complex loop cases.
97
98 /*enum LoopBody
99  {
100  LOOPBODY_READ_UNIFORM = 0,
101  LOOPBODY_READ_UNIFORM_ARRAY,
102  LOOPBODY_READ_
103  };*/
104
105 enum LoopType
106 {
107         LOOPTYPE_FOR = 0,
108         LOOPTYPE_WHILE,
109         LOOPTYPE_DO_WHILE,
110
111         LOOPTYPE_LAST
112 };
113
114 static const char* getLoopTypeName(LoopType loopType)
115 {
116         static const char* s_names[] = { "for", "while", "do_while" };
117
118         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPTYPE_LAST);
119         DE_ASSERT(deInBounds32((int)loopType, 0, LOOPTYPE_LAST));
120         return s_names[(int)loopType];
121 }
122
123 enum LoopCountType
124 {
125         LOOPCOUNT_CONSTANT = 0,
126         LOOPCOUNT_UNIFORM,
127         LOOPCOUNT_DYNAMIC,
128
129         LOOPCOUNT_LAST
130 };
131
132 static const char* getLoopCountTypeName(LoopCountType countType)
133 {
134         static const char* s_names[] = { "constant", "uniform", "dynamic" };
135
136         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPCOUNT_LAST);
137         DE_ASSERT(deInBounds32((int)countType, 0, LOOPCOUNT_LAST));
138         return s_names[(int)countType];
139 }
140
141 static void evalLoop0Iters(ShaderEvalContext& c)
142 {
143         c.color.xyz() = c.coords.swizzle(0, 1, 2);
144 }
145 static void evalLoop1Iters(ShaderEvalContext& c)
146 {
147         c.color.xyz() = c.coords.swizzle(1, 2, 3);
148 }
149 static void evalLoop2Iters(ShaderEvalContext& c)
150 {
151         c.color.xyz() = c.coords.swizzle(2, 3, 0);
152 }
153 static void evalLoop3Iters(ShaderEvalContext& c)
154 {
155         c.color.xyz() = c.coords.swizzle(3, 0, 1);
156 }
157
158 static ShaderEvalFunc getLoopEvalFunc(int numIters)
159 {
160         switch (numIters % 4)
161         {
162         case 0:
163                 return evalLoop0Iters;
164         case 1:
165                 return evalLoop1Iters;
166         case 2:
167                 return evalLoop2Iters;
168         case 3:
169                 return evalLoop3Iters;
170         }
171
172         DE_ASSERT(DE_FALSE && "Invalid loop iteration count.");
173         return NULL;
174 }
175
176 // ShaderLoopCase
177
178 class ShaderLoopCase : public ShaderRenderCase
179 {
180 public:
181         ShaderLoopCase(Context& context, const char* name, const char* description, bool isVertexCase,
182                                    ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource);
183         virtual ~ShaderLoopCase(void);
184
185 private:
186         ShaderLoopCase(const ShaderLoopCase&);                    // not allowed!
187         ShaderLoopCase& operator=(const ShaderLoopCase&); // not allowed!
188
189         virtual void setup(deUint32 programID);
190         virtual void setupUniforms(deUint32 programID, const Vec4& constCoords);
191 };
192
193 ShaderLoopCase::ShaderLoopCase(Context& context, const char* name, const char* description, bool isVertexCase,
194                                                            ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource)
195         : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
196                                            description, isVertexCase, evalFunc)
197 {
198         m_vertShaderSource = vertShaderSource;
199         m_fragShaderSource = fragShaderSource;
200 }
201
202 ShaderLoopCase::~ShaderLoopCase(void)
203 {
204 }
205
206 void ShaderLoopCase::setup(deUint32 programID)
207 {
208         DE_UNREF(programID);
209 }
210
211 void ShaderLoopCase::setupUniforms(deUint32 programID, const Vec4& constCoords)
212 {
213         DE_UNREF(programID);
214         DE_UNREF(constCoords);
215 }
216
217 // Test case creation.
218
219 static ShaderLoopCase* createGenericLoopCase(Context& context, glu::GLSLVersion glslVersion, const char* caseName,
220                                                                                          const char* description, bool isVertexCase, LoopType loopType,
221                                                                                          LoopCountType loopCountType, Precision loopCountPrecision,
222                                                                                          DataType loopCountDataType)
223 {
224         std::ostringstream  vtx;
225         std::ostringstream  frag;
226         std::ostringstream& op = isVertexCase ? vtx : frag;
227
228         vtx << getGLSLVersionDeclaration(glslVersion) << "\n";
229         frag << getGLSLVersionDeclaration(glslVersion) << "\n";
230
231         vtx << "in highp vec4 a_position;\n";
232         vtx << "in highp vec4 a_coords;\n";
233         frag << "layout(location = 0) out mediump vec4 o_color;\n";
234
235         if (loopCountType == LOOPCOUNT_DYNAMIC)
236                 vtx << "in mediump float a_one;\n";
237
238         if (isVertexCase)
239         {
240                 vtx << "out mediump vec3 v_color;\n";
241                 frag << "in mediump vec3 v_color;\n";
242         }
243         else
244         {
245                 vtx << "out mediump vec4 v_coords;\n";
246                 frag << "in mediump vec4 v_coords;\n";
247
248                 if (loopCountType == LOOPCOUNT_DYNAMIC)
249                 {
250                         vtx << "out mediump float v_one;\n";
251                         frag << "in mediump float v_one;\n";
252                 }
253         }
254
255         // \todo [petri] Pass numLoopIters from outside?
256         int  numLoopIters = 3;
257         bool isIntCounter = isDataTypeIntOrIVec(loopCountDataType);
258
259         if (isIntCounter)
260         {
261                 if (loopCountType == LOOPCOUNT_UNIFORM || loopCountType == LOOPCOUNT_DYNAMIC)
262                         op << "uniform ${COUNTER_PRECISION} int " << getIntUniformName(numLoopIters) << ";\n";
263         }
264         else
265         {
266                 if (loopCountType == LOOPCOUNT_UNIFORM || loopCountType == LOOPCOUNT_DYNAMIC)
267                         op << "uniform ${COUNTER_PRECISION} float " << getFloatFractionUniformName(numLoopIters) << ";\n";
268
269                 if (numLoopIters != 1)
270                         op << "uniform ${COUNTER_PRECISION} float uf_one;\n";
271         }
272
273         vtx << "\n";
274         vtx << "void main()\n";
275         vtx << "{\n";
276         vtx << "    gl_Position = a_position;\n";
277
278         frag << "\n";
279         frag << "void main()\n";
280         frag << "{\n";
281
282         if (isVertexCase)
283                 vtx << "    ${PRECISION} vec4 coords = a_coords;\n";
284         else
285                 frag << "   ${PRECISION} vec4 coords = v_coords;\n";
286
287         if (loopCountType == LOOPCOUNT_DYNAMIC)
288         {
289                 if (isIntCounter)
290                 {
291                         if (isVertexCase)
292                                 vtx << "    ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n";
293                         else
294                                 frag << "   ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n";
295                 }
296                 else
297                 {
298                         if (isVertexCase)
299                                 vtx << "    ${COUNTER_PRECISION} float one = a_one;\n";
300                         else
301                                 frag << "   ${COUNTER_PRECISION} float one = v_one;\n";
302                 }
303         }
304
305         // Read array.
306         op << " ${PRECISION} vec4 res = coords;\n";
307
308         // Loop iteration count.
309         string iterMaxStr;
310
311         if (isIntCounter)
312         {
313                 if (loopCountType == LOOPCOUNT_CONSTANT)
314                         iterMaxStr = de::toString(numLoopIters);
315                 else if (loopCountType == LOOPCOUNT_UNIFORM)
316                         iterMaxStr = getIntUniformName(numLoopIters);
317                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
318                         iterMaxStr = string(getIntUniformName(numLoopIters)) + "*one";
319                 else
320                         DE_ASSERT(false);
321         }
322         else
323         {
324                 if (loopCountType == LOOPCOUNT_CONSTANT)
325                         iterMaxStr = "1.0";
326                 else if (loopCountType == LOOPCOUNT_UNIFORM)
327                         iterMaxStr = "uf_one";
328                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
329                         iterMaxStr = "uf_one*one";
330                 else
331                         DE_ASSERT(false);
332         }
333
334         // Loop operations.
335         string initValue                = isIntCounter ? "0" : "0.05";
336         string loopCountDeclStr = "${COUNTER_PRECISION} ${LOOP_VAR_TYPE} ndx = " + initValue;
337         string loopCmpStr               = ("ndx < " + iterMaxStr);
338         string incrementStr;
339         if (isIntCounter)
340                 incrementStr = "ndx++";
341         else
342         {
343                 if (loopCountType == LOOPCOUNT_CONSTANT)
344                         incrementStr = string("ndx += ") + de::toString(1.0f / static_cast<float>(numLoopIters));
345                 else if (loopCountType == LOOPCOUNT_UNIFORM)
346                         incrementStr = string("ndx += ") + getFloatFractionUniformName(numLoopIters);
347                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
348                         incrementStr = string("ndx += ") + getFloatFractionUniformName(numLoopIters) + "*one";
349                 else
350                         DE_ASSERT(false);
351         }
352
353         string loopPrefix;
354         string loopPostfix;
355
356         // Loop body.
357         string loopBody;
358
359         loopBody = "        res = res.yzwx;\n";
360
361         if (loopType == LOOPTYPE_FOR)
362         {
363                 op << " for (" + loopCountDeclStr + "; " + loopCmpStr + "; " + incrementStr + ")\n";
364                 op << " {\n";
365                 op << loopBody;
366                 op << " }\n";
367         }
368         else if (loopType == LOOPTYPE_WHILE)
369         {
370                 op << "\t" << loopCountDeclStr + ";\n";
371                 op << " while (" + loopCmpStr + ")\n";
372                 op << " {\n";
373                 op << loopBody;
374                 op << "\t\t" + incrementStr + ";\n";
375                 op << " }\n";
376         }
377         else if (loopType == LOOPTYPE_DO_WHILE)
378         {
379                 op << "\t" << loopCountDeclStr + ";\n";
380                 op << " do\n";
381                 op << " {\n";
382                 op << loopBody;
383                 op << "\t\t" + incrementStr + ";\n";
384                 op << " } while (" + loopCmpStr + ");\n";
385         }
386         else
387                 DE_ASSERT(false);
388
389         if (isVertexCase)
390         {
391                 vtx << "    v_color = res.rgb;\n";
392                 frag << "   o_color = vec4(v_color.rgb, 1.0);\n";
393         }
394         else
395         {
396                 vtx << "    v_coords = a_coords;\n";
397                 frag << "   o_color = vec4(res.rgb, 1.0);\n";
398
399                 if (loopCountType == LOOPCOUNT_DYNAMIC)
400                         vtx << "    v_one = a_one;\n";
401         }
402
403         vtx << "}\n";
404         frag << "}\n";
405
406         // Fill in shader templates.
407         map<string, string> params;
408         params.insert(pair<string, string>("LOOP_VAR_TYPE", getDataTypeName(loopCountDataType)));
409         params.insert(pair<string, string>("PRECISION", "mediump"));
410         params.insert(pair<string, string>("COUNTER_PRECISION", getPrecisionName(loopCountPrecision)));
411
412         StringTemplate vertTemplate(vtx.str().c_str());
413         StringTemplate fragTemplate(frag.str().c_str());
414         string             vertexShaderSource   = vertTemplate.specialize(params);
415         string             fragmentShaderSource = fragTemplate.specialize(params);
416
417         // Create the case.
418         ShaderEvalFunc evalFunc = getLoopEvalFunc(numLoopIters);
419         return new ShaderLoopCase(context, caseName, description, isVertexCase, evalFunc, vertexShaderSource.c_str(),
420                                                           fragmentShaderSource.c_str());
421 }
422
423 // \todo [petri] Generalize to float as well?
424 static ShaderLoopCase* createSpecialLoopCase(Context& context, glu::GLSLVersion glslVersion, const char* caseName,
425                                                                                          const char* description, bool isVertexCase, LoopCase loopCase,
426                                                                                          LoopType loopType, LoopCountType loopCountType)
427 {
428         std::ostringstream  vtx;
429         std::ostringstream  frag;
430         std::ostringstream& op = isVertexCase ? vtx : frag;
431
432         vtx << getGLSLVersionDeclaration(glslVersion) << "\n";
433         frag << getGLSLVersionDeclaration(glslVersion) << "\n";
434
435         vtx << "in highp vec4 a_position;\n";
436         vtx << "in highp vec4 a_coords;\n";
437         frag << "layout(location = 0) out mediump vec4 o_color;\n";
438
439         if (loopCountType == LOOPCOUNT_DYNAMIC)
440                 vtx << "in mediump float a_one;\n";
441
442         // Attribute and varyings.
443         if (isVertexCase)
444         {
445                 vtx << "out mediump vec3 v_color;\n";
446                 frag << "in mediump vec3 v_color;\n";
447         }
448         else
449         {
450                 vtx << "out mediump vec4 v_coords;\n";
451                 frag << "in mediump vec4 v_coords;\n";
452
453                 if (loopCountType == LOOPCOUNT_DYNAMIC)
454                 {
455                         vtx << "out mediump float v_one;\n";
456                         frag << "in mediump float v_one;\n";
457                 }
458         }
459
460         if (loopCase == LOOPCASE_SELECT_ITERATION_COUNT)
461                 op << "uniform bool ub_true;\n";
462
463         op << "uniform ${COUNTER_PRECISION} int ui_zero, ui_one, ui_two, ui_three, ui_four, ui_five, ui_six;\n";
464         if (loopCase == LOOPCASE_101_ITERATIONS)
465                 op << "uniform ${COUNTER_PRECISION} int ui_oneHundredOne;\n";
466
467         int iterCount = 3; // value to use in loop
468         int numIters  = 3; // actual number of iterations
469
470         vtx << "\n";
471         vtx << "void main()\n";
472         vtx << "{\n";
473         vtx << "    gl_Position = a_position;\n";
474
475         frag << "\n";
476         frag << "void main()\n";
477         frag << "{\n";
478
479         if (loopCountType == LOOPCOUNT_DYNAMIC)
480         {
481                 if (isVertexCase)
482                         vtx << "    ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n";
483                 else
484                         frag << "   ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n";
485         }
486
487         if (isVertexCase)
488                 vtx << "    ${PRECISION} vec4 coords = a_coords;\n";
489         else
490                 frag << "   ${PRECISION} vec4 coords = v_coords;\n";
491
492         // Read array.
493         op << " ${PRECISION} vec4 res = coords;\n";
494
495         // Handle all loop types.
496         string counterPrecisionStr = "mediump";
497         string forLoopStr;
498         string whileLoopStr;
499         string doWhileLoopPreStr;
500         string doWhileLoopPostStr;
501
502         if (loopType == LOOPTYPE_FOR)
503         {
504                 switch (loopCase)
505                 {
506                 case LOOPCASE_EMPTY_BODY:
507                         numIters = 0;
508                         op << " ${FOR_LOOP} {}\n";
509                         break;
510
511                 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
512                         numIters = 0;
513                         op << " for (;;) { break; res = res.yzwx; }\n";
514                         break;
515
516                 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
517                         numIters = 1;
518                         op << " for (;;) { res = res.yzwx; break; }\n";
519                         break;
520
521                 case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
522                         numIters = 2;
523                         op << " ${COUNTER_PRECISION} int i = 0;\n";
524                         op << " for (;;) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n";
525                         break;
526
527                 case LOOPCASE_SINGLE_STATEMENT:
528                         op << " ${FOR_LOOP} res = res.yzwx;\n";
529                         break;
530
531                 case LOOPCASE_COMPOUND_STATEMENT:
532                         iterCount = 2;
533                         numIters  = 2 * iterCount;
534                         op << " ${FOR_LOOP} { res = res.yzwx; res = res.yzwx; }\n";
535                         break;
536
537                 case LOOPCASE_SEQUENCE_STATEMENT:
538                         iterCount = 2;
539                         numIters  = 2 * iterCount;
540                         op << " ${FOR_LOOP} res = res.yzwx, res = res.yzwx;\n";
541                         break;
542
543                 case LOOPCASE_NO_ITERATIONS:
544                         iterCount = 0;
545                         numIters  = 0;
546                         op << " ${FOR_LOOP} res = res.yzwx;\n";
547                         break;
548
549                 case LOOPCASE_SINGLE_ITERATION:
550                         iterCount = 1;
551                         numIters  = 1;
552                         op << " ${FOR_LOOP} res = res.yzwx;\n";
553                         break;
554
555                 case LOOPCASE_SELECT_ITERATION_COUNT:
556                         op << " for (int i = 0; i < (ub_true ? ${ITER_COUNT} : 0); i++) res = res.yzwx;\n";
557                         break;
558
559                 case LOOPCASE_CONDITIONAL_CONTINUE:
560                         numIters = iterCount - 1;
561                         op << " ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n";
562                         break;
563
564                 case LOOPCASE_UNCONDITIONAL_CONTINUE:
565                         op << " ${FOR_LOOP} { res = res.yzwx; continue; }\n";
566                         break;
567
568                 case LOOPCASE_ONLY_CONTINUE:
569                         numIters = 0;
570                         op << " ${FOR_LOOP} { continue; }\n";
571                         break;
572
573                 case LOOPCASE_DOUBLE_CONTINUE:
574                         numIters = iterCount - 1;
575                         op << " ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; continue; }\n";
576                         break;
577
578                 case LOOPCASE_CONDITIONAL_BREAK:
579                         numIters = 2;
580                         op << " ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx; }\n";
581                         break;
582
583                 case LOOPCASE_UNCONDITIONAL_BREAK:
584                         numIters = 1;
585                         op << " ${FOR_LOOP} { res = res.yzwx; break; }\n";
586                         break;
587
588                 case LOOPCASE_PRE_INCREMENT:
589                         op << " for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx; }\n";
590                         break;
591
592                 case LOOPCASE_POST_INCREMENT:
593                         op << " ${FOR_LOOP} { res = res.yzwx; }\n";
594                         break;
595
596                 case LOOPCASE_MIXED_BREAK_CONTINUE:
597                         numIters  = 2;
598                         iterCount = 5;
599                         op << " ${FOR_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n";
600                         break;
601
602                 case LOOPCASE_VECTOR_COUNTER:
603                         op << " for (${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0); i.x < i.z; i.x += i.y) { res = "
604                                   "res.yzwx; }\n";
605                         break;
606
607                 case LOOPCASE_101_ITERATIONS:
608                         numIters = iterCount = 101;
609                         op << " ${FOR_LOOP} res = res.yzwx;\n";
610                         break;
611
612                 case LOOPCASE_SEQUENCE:
613                         iterCount = 5;
614                         numIters  = 5;
615                         op << " ${COUNTER_PRECISION} int i;\n";
616                         op << " for (i = 0; i < ${TWO}; i++) { res = res.yzwx; }\n";
617                         op << " for (; i < ${ITER_COUNT}; i++) { res = res.yzwx; }\n";
618                         break;
619
620                 case LOOPCASE_NESTED:
621                         numIters = 2 * iterCount;
622                         op << " for (${COUNTER_PRECISION} int i = 0; i < ${TWO}; i++)\n";
623                         op << " {\n";
624                         op << "     for (${COUNTER_PRECISION} int j = 0; j < ${ITER_COUNT}; j++)\n";
625                         op << "         res = res.yzwx;\n";
626                         op << " }\n";
627                         break;
628
629                 case LOOPCASE_NESTED_SEQUENCE:
630                         numIters = 3 * iterCount;
631                         op << " for (${COUNTER_PRECISION} int i = 0; i < ${ITER_COUNT}; i++)\n";
632                         op << " {\n";
633                         op << "     for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
634                         op << "         res = res.yzwx;\n";
635                         op << "     for (${COUNTER_PRECISION} int j = 0; j < ${ONE}; j++)\n";
636                         op << "         res = res.yzwx;\n";
637                         op << " }\n";
638                         break;
639
640                 case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
641                         numIters = 2;
642                         op << " ${FOR_LOOP}\n";
643                         op << " {\n";
644                         op << "     res = coords; // ignore outer loop effect \n";
645                         op << "     for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
646                         op << "         res = res.yzwx;\n";
647                         op << " }\n";
648                         break;
649
650                 case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
651                         numIters = iterCount;
652                         op << " ${FOR_LOOP}\n";
653                         op << " {\n";
654                         op << "     res = coords.wxyz;\n";
655                         op << "     for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
656                         op << "         res = res.yzwx;\n";
657                         op << "     coords = res;\n";
658                         op << " }\n";
659                         break;
660
661                 default:
662                         DE_ASSERT(false);
663                 }
664
665                 if (loopCountType == LOOPCOUNT_CONSTANT)
666                         forLoopStr =
667                                 string("for (") + counterPrecisionStr + " int i = 0; i < " + de::toString(iterCount) + "; i++)";
668                 else if (loopCountType == LOOPCOUNT_UNIFORM)
669                         forLoopStr =
670                                 string("for (") + counterPrecisionStr + " int i = 0; i < " + getIntUniformName(iterCount) + "; i++)";
671                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
672                         forLoopStr = string("for (") + counterPrecisionStr + " int i = 0; i < one*" + getIntUniformName(iterCount) +
673                                                  "; i++)";
674                 else
675                         DE_ASSERT(false);
676         }
677         else if (loopType == LOOPTYPE_WHILE)
678         {
679                 switch (loopCase)
680                 {
681                 case LOOPCASE_EMPTY_BODY:
682                         numIters = 0;
683                         op << " ${WHILE_LOOP} {}\n";
684                         break;
685
686                 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
687                         numIters = 0;
688                         op << " while (true) { break; res = res.yzwx; }\n";
689                         break;
690
691                 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
692                         numIters = 1;
693                         op << " while (true) { res = res.yzwx; break; }\n";
694                         break;
695
696                 case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
697                         numIters = 2;
698                         op << " ${COUNTER_PRECISION} int i = 0;\n";
699                         op << " while (true) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n";
700                         break;
701
702                 case LOOPCASE_SINGLE_STATEMENT:
703                         op << " ${WHILE_LOOP} res = res.yzwx;\n";
704                         break;
705
706                 case LOOPCASE_COMPOUND_STATEMENT:
707                         iterCount = 2;
708                         numIters  = 2 * iterCount;
709                         op << " ${WHILE_LOOP} { res = res.yzwx; res = res.yzwx; }\n";
710                         break;
711
712                 case LOOPCASE_SEQUENCE_STATEMENT:
713                         iterCount = 2;
714                         numIters  = 2 * iterCount;
715                         op << " ${WHILE_LOOP} res = res.yzwx, res = res.yzwx;\n";
716                         break;
717
718                 case LOOPCASE_NO_ITERATIONS:
719                         iterCount = 0;
720                         numIters  = 0;
721                         op << " ${WHILE_LOOP} res = res.yzwx;\n";
722                         break;
723
724                 case LOOPCASE_SINGLE_ITERATION:
725                         iterCount = 1;
726                         numIters  = 1;
727                         op << " ${WHILE_LOOP} res = res.yzwx;\n";
728                         break;
729
730                 case LOOPCASE_SELECT_ITERATION_COUNT:
731                         op << " ${COUNTER_PRECISION} int i = 0;\n";
732                         op << " while (i < (ub_true ? ${ITER_COUNT} : 0)) { res = res.yzwx; i++; }\n";
733                         break;
734
735                 case LOOPCASE_CONDITIONAL_CONTINUE:
736                         numIters = iterCount - 1;
737                         op << " ${WHILE_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n";
738                         break;
739
740                 case LOOPCASE_UNCONDITIONAL_CONTINUE:
741                         op << " ${WHILE_LOOP} { res = res.yzwx; continue; }\n";
742                         break;
743
744                 case LOOPCASE_ONLY_CONTINUE:
745                         numIters = 0;
746                         op << " ${WHILE_LOOP} { continue; }\n";
747                         break;
748
749                 case LOOPCASE_DOUBLE_CONTINUE:
750                         numIters = iterCount - 1;
751                         op << " ${WHILE_LOOP} { if (i == ${ONE}) continue; res = res.yzwx; continue; }\n";
752                         break;
753
754                 case LOOPCASE_CONDITIONAL_BREAK:
755                         numIters = 2;
756                         op << " ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx; }\n";
757                         break;
758
759                 case LOOPCASE_UNCONDITIONAL_BREAK:
760                         numIters = 1;
761                         op << " ${WHILE_LOOP} { res = res.yzwx; break; }\n";
762                         break;
763
764                 case LOOPCASE_PRE_INCREMENT:
765                         numIters = iterCount - 1;
766                         op << " ${COUNTER_PRECISION} int i = 0;\n";
767                         op << " while (++i < ${ITER_COUNT}) { res = res.yzwx; }\n";
768                         break;
769
770                 case LOOPCASE_POST_INCREMENT:
771                         op << " ${COUNTER_PRECISION} int i = 0;\n";
772                         op << " while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n";
773                         break;
774
775                 case LOOPCASE_MIXED_BREAK_CONTINUE:
776                         numIters  = 2;
777                         iterCount = 5;
778                         op << " ${WHILE_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n";
779                         break;
780
781                 case LOOPCASE_VECTOR_COUNTER:
782                         op << " ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n";
783                         op << " while (i.x < i.z) { res = res.yzwx; i.x += i.y; }\n";
784                         break;
785
786                 case LOOPCASE_101_ITERATIONS:
787                         numIters = iterCount = 101;
788                         op << " ${WHILE_LOOP} res = res.yzwx;\n";
789                         break;
790
791                 case LOOPCASE_SEQUENCE:
792                         iterCount = 6;
793                         numIters  = iterCount - 1;
794                         op << " ${COUNTER_PRECISION} int i = 0;\n";
795                         op << " while (i++ < ${TWO}) { res = res.yzwx; }\n";
796                         op << " while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n"; // \note skips one iteration
797                         break;
798
799                 case LOOPCASE_NESTED:
800                         numIters = 2 * iterCount;
801                         op << " ${COUNTER_PRECISION} int i = 0;\n";
802                         op << " while (i++ < ${TWO})\n";
803                         op << " {\n";
804                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
805                         op << "     while (j++ < ${ITER_COUNT})\n";
806                         op << "         res = res.yzwx;\n";
807                         op << " }\n";
808                         break;
809
810                 case LOOPCASE_NESTED_SEQUENCE:
811                         numIters = 2 * iterCount;
812                         op << " ${COUNTER_PRECISION} int i = 0;\n";
813                         op << " while (i++ < ${ITER_COUNT})\n";
814                         op << " {\n";
815                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
816                         op << "     while (j++ < ${ONE})\n";
817                         op << "         res = res.yzwx;\n";
818                         op << "     while (j++ < ${THREE})\n"; // \note skips one iteration
819                         op << "         res = res.yzwx;\n";
820                         op << " }\n";
821                         break;
822
823                 case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
824                         numIters = 2;
825                         op << " ${WHILE_LOOP}\n";
826                         op << " {\n";
827                         op << "     res = coords; // ignore outer loop effect \n";
828                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
829                         op << "     while (j++ < ${TWO})\n";
830                         op << "         res = res.yzwx;\n";
831                         op << " }\n";
832                         break;
833
834                 case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
835                         numIters = iterCount;
836                         op << " ${WHILE_LOOP}\n";
837                         op << " {\n";
838                         op << "     res = coords.wxyz;\n";
839                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
840                         op << "     while (j++ < ${TWO})\n";
841                         op << "         res = res.yzwx;\n";
842                         op << "     coords = res;\n";
843                         op << " }\n";
844                         break;
845
846                 default:
847                         DE_ASSERT(false);
848                 }
849
850                 if (loopCountType == LOOPCOUNT_CONSTANT)
851                         whileLoopStr =
852                                 string("\t") + counterPrecisionStr + " int i = 0;\n" + " while(i++ < " + de::toString(iterCount) + ")";
853                 else if (loopCountType == LOOPCOUNT_UNIFORM)
854                         whileLoopStr = string("\t") + counterPrecisionStr + " int i = 0;\n" + " while(i++ < " +
855                                                    getIntUniformName(iterCount) + ")";
856                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
857                         whileLoopStr = string("\t") + counterPrecisionStr + " int i = 0;\n" + " while(i++ < one*" +
858                                                    getIntUniformName(iterCount) + ")";
859                 else
860                         DE_ASSERT(false);
861         }
862         else
863         {
864                 DE_ASSERT(loopType == LOOPTYPE_DO_WHILE);
865
866                 switch (loopCase)
867                 {
868                 case LOOPCASE_EMPTY_BODY:
869                         numIters = 0;
870                         op << " ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n";
871                         break;
872
873                 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
874                         numIters = 0;
875                         op << " do { break; res = res.yzwx; } while (true);\n";
876                         break;
877
878                 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
879                         numIters = 1;
880                         op << " do { res = res.yzwx; break; } while (true);\n";
881                         break;
882
883                 case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
884                         numIters = 2;
885                         op << " ${COUNTER_PRECISION} int i = 0;\n";
886                         op << " do { res = res.yzwx; if (i == ${ONE}) break; i++; } while (true);\n";
887                         break;
888
889                 case LOOPCASE_SINGLE_STATEMENT:
890                         op << " ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n";
891                         break;
892
893                 case LOOPCASE_COMPOUND_STATEMENT:
894                         iterCount = 2;
895                         numIters  = 2 * iterCount;
896                         op << " ${DO_WHILE_PRE} { res = res.yzwx; res = res.yzwx; } ${DO_WHILE_POST}\n";
897                         break;
898
899                 case LOOPCASE_SEQUENCE_STATEMENT:
900                         iterCount = 2;
901                         numIters  = 2 * iterCount;
902                         op << " ${DO_WHILE_PRE} res = res.yzwx, res = res.yzwx; ${DO_WHILE_POST}\n";
903                         break;
904
905                 case LOOPCASE_NO_ITERATIONS:
906                         DE_ASSERT(false);
907                         break;
908
909                 case LOOPCASE_SINGLE_ITERATION:
910                         iterCount = 1;
911                         numIters  = 1;
912                         op << " ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n";
913                         break;
914
915                 case LOOPCASE_SELECT_ITERATION_COUNT:
916                         op << " ${COUNTER_PRECISION} int i = 0;\n";
917                         op << " do { res = res.yzwx; } while (++i < (ub_true ? ${ITER_COUNT} : 0));\n";
918                         break;
919
920                 case LOOPCASE_CONDITIONAL_CONTINUE:
921                         numIters = iterCount - 1;
922                         op << " ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; } ${DO_WHILE_POST}\n";
923                         break;
924
925                 case LOOPCASE_UNCONDITIONAL_CONTINUE:
926                         op << " ${DO_WHILE_PRE} { res = res.yzwx; continue; } ${DO_WHILE_POST}\n";
927                         break;
928
929                 case LOOPCASE_ONLY_CONTINUE:
930                         numIters = 0;
931                         op << " ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n";
932                         break;
933
934                 case LOOPCASE_DOUBLE_CONTINUE:
935                         numIters = iterCount - 1;
936                         op << " ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; continue; } ${DO_WHILE_POST}\n";
937                         break;
938
939                 case LOOPCASE_CONDITIONAL_BREAK:
940                         numIters = 2;
941                         op << " ${DO_WHILE_PRE} { res = res.yzwx; if (i == ${ONE}) break; } ${DO_WHILE_POST}\n";
942                         break;
943
944                 case LOOPCASE_UNCONDITIONAL_BREAK:
945                         numIters = 1;
946                         op << " ${DO_WHILE_PRE} { res = res.yzwx; break; } ${DO_WHILE_POST}\n";
947                         break;
948
949                 case LOOPCASE_PRE_INCREMENT:
950                         op << " ${COUNTER_PRECISION} int i = 0;\n";
951                         op << " do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n";
952                         break;
953
954                 case LOOPCASE_POST_INCREMENT:
955                         numIters = iterCount + 1;
956                         op << " ${COUNTER_PRECISION} int i = 0;\n";
957                         op << " do { res = res.yzwx; } while (i++ < ${ITER_COUNT});\n";
958                         break;
959
960                 case LOOPCASE_MIXED_BREAK_CONTINUE:
961                         numIters  = 2;
962                         iterCount = 5;
963                         op << " ${DO_WHILE_PRE} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; } "
964                                   "${DO_WHILE_POST}\n";
965                         break;
966
967                 case LOOPCASE_VECTOR_COUNTER:
968                         op << " ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n";
969                         op << " do { res = res.yzwx; } while ((i.x += i.y) < i.z);\n";
970                         break;
971
972                 case LOOPCASE_101_ITERATIONS:
973                         numIters = iterCount = 101;
974                         op << " ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n";
975                         break;
976
977                 case LOOPCASE_SEQUENCE:
978                         iterCount = 5;
979                         numIters  = 5;
980                         op << " ${COUNTER_PRECISION} int i = 0;\n";
981                         op << " do { res = res.yzwx; } while (++i < ${TWO});\n";
982                         op << " do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n";
983                         break;
984
985                 case LOOPCASE_NESTED:
986                         numIters = 2 * iterCount;
987                         op << " ${COUNTER_PRECISION} int i = 0;\n";
988                         op << " do\n";
989                         op << " {\n";
990                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
991                         op << "     do\n";
992                         op << "         res = res.yzwx;\n";
993                         op << "     while (++j < ${ITER_COUNT});\n";
994                         op << " } while (++i < ${TWO});\n";
995                         break;
996
997                 case LOOPCASE_NESTED_SEQUENCE:
998                         numIters = 3 * iterCount;
999                         op << " ${COUNTER_PRECISION} int i = 0;\n";
1000                         op << " do\n";
1001                         op << " {\n";
1002                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
1003                         op << "     do\n";
1004                         op << "         res = res.yzwx;\n";
1005                         op << "     while (++j < ${TWO});\n";
1006                         op << "     do\n";
1007                         op << "         res = res.yzwx;\n";
1008                         op << "     while (++j < ${THREE});\n";
1009                         op << " } while (++i < ${ITER_COUNT});\n";
1010                         break;
1011
1012                 case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
1013                         numIters = 2;
1014                         op << " ${DO_WHILE_PRE}\n";
1015                         op << " {\n";
1016                         op << "     res = coords; // ignore outer loop effect \n";
1017                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
1018                         op << "     do\n";
1019                         op << "         res = res.yzwx;\n";
1020                         op << "     while (++j < ${TWO});\n";
1021                         op << " } ${DO_WHILE_POST}\n";
1022                         break;
1023
1024                 case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
1025                         numIters = iterCount;
1026                         op << " ${DO_WHILE_PRE}\n";
1027                         op << " {\n";
1028                         op << "     res = coords.wxyz;\n";
1029                         op << "     ${COUNTER_PRECISION} int j = 0;\n";
1030                         op << "     while (j++ < ${TWO})\n";
1031                         op << "         res = res.yzwx;\n";
1032                         op << "     coords = res;\n";
1033                         op << " } ${DO_WHILE_POST}\n";
1034                         break;
1035
1036                 default:
1037                         DE_ASSERT(false);
1038                 }
1039
1040                 doWhileLoopPreStr = string("\t") + counterPrecisionStr + " int i = 0;\n" + "\tdo ";
1041                 if (loopCountType == LOOPCOUNT_CONSTANT)
1042                         doWhileLoopPostStr = string(" while (++i < ") + de::toString(iterCount) + ");\n";
1043                 else if (loopCountType == LOOPCOUNT_UNIFORM)
1044                         doWhileLoopPostStr = string(" while (++i < ") + getIntUniformName(iterCount) + ");\n";
1045                 else if (loopCountType == LOOPCOUNT_DYNAMIC)
1046                         doWhileLoopPostStr = string(" while (++i < one*") + getIntUniformName(iterCount) + ");\n";
1047                 else
1048                         DE_ASSERT(false);
1049         }
1050
1051         // Shader footers.
1052         if (isVertexCase)
1053         {
1054                 vtx << "    v_color = res.rgb;\n";
1055                 frag << "   o_color = vec4(v_color.rgb, 1.0);\n";
1056         }
1057         else
1058         {
1059                 vtx << "    v_coords = a_coords;\n";
1060                 frag << "   o_color = vec4(res.rgb, 1.0);\n";
1061
1062                 if (loopCountType == LOOPCOUNT_DYNAMIC)
1063                         vtx << "    v_one = a_one;\n";
1064         }
1065
1066         vtx << "}\n";
1067         frag << "}\n";
1068
1069         // Constants.
1070         string oneStr;
1071         string twoStr;
1072         string threeStr;
1073         string iterCountStr;
1074
1075         if (loopCountType == LOOPCOUNT_CONSTANT)
1076         {
1077                 oneStr           = "1";
1078                 twoStr           = "2";
1079                 threeStr         = "3";
1080                 iterCountStr = de::toString(iterCount);
1081         }
1082         else if (loopCountType == LOOPCOUNT_UNIFORM)
1083         {
1084                 oneStr           = "ui_one";
1085                 twoStr           = "ui_two";
1086                 threeStr         = "ui_three";
1087                 iterCountStr = getIntUniformName(iterCount);
1088         }
1089         else if (loopCountType == LOOPCOUNT_DYNAMIC)
1090         {
1091                 oneStr           = "one*ui_one";
1092                 twoStr           = "one*ui_two";
1093                 threeStr         = "one*ui_three";
1094                 iterCountStr = string("one*") + getIntUniformName(iterCount);
1095         }
1096         else
1097                 DE_ASSERT(false);
1098
1099         // Fill in shader templates.
1100         map<string, string> params;
1101         params.insert(pair<string, string>("PRECISION", "mediump"));
1102         params.insert(pair<string, string>("ITER_COUNT", iterCountStr));
1103         params.insert(pair<string, string>("COUNTER_PRECISION", counterPrecisionStr));
1104         params.insert(pair<string, string>("FOR_LOOP", forLoopStr));
1105         params.insert(pair<string, string>("WHILE_LOOP", whileLoopStr));
1106         params.insert(pair<string, string>("DO_WHILE_PRE", doWhileLoopPreStr));
1107         params.insert(pair<string, string>("DO_WHILE_POST", doWhileLoopPostStr));
1108         params.insert(pair<string, string>("ONE", oneStr));
1109         params.insert(pair<string, string>("TWO", twoStr));
1110         params.insert(pair<string, string>("THREE", threeStr));
1111
1112         StringTemplate vertTemplate(vtx.str().c_str());
1113         StringTemplate fragTemplate(frag.str().c_str());
1114         string             vertexShaderSource   = vertTemplate.specialize(params);
1115         string             fragmentShaderSource = fragTemplate.specialize(params);
1116
1117         // Create the case.
1118         ShaderEvalFunc evalFunc = getLoopEvalFunc(numIters);
1119         return new ShaderLoopCase(context, caseName, description, isVertexCase, evalFunc, vertexShaderSource.c_str(),
1120                                                           fragmentShaderSource.c_str());
1121 }
1122
1123 // ShaderLoopTests.
1124
1125 ShaderLoopTests::ShaderLoopTests(Context& context, glu::GLSLVersion glslVersion)
1126         : TestCaseGroup(context, "loops", "Loop Tests"), m_glslVersion(glslVersion)
1127 {
1128 }
1129
1130 ShaderLoopTests::~ShaderLoopTests(void)
1131 {
1132 }
1133
1134 void ShaderLoopTests::init(void)
1135 {
1136         // Loop cases.
1137
1138         static const DataType s_countDataType[] = { TYPE_INT, TYPE_FLOAT };
1139
1140         static const ShaderType s_shaderTypes[] = { SHADERTYPE_VERTEX, SHADERTYPE_FRAGMENT };
1141
1142         for (int loopType = 0; loopType < LOOPTYPE_LAST; loopType++)
1143         {
1144                 const char* loopTypeName = getLoopTypeName((LoopType)loopType);
1145
1146                 for (int loopCountType = 0; loopCountType < LOOPCOUNT_LAST; loopCountType++)
1147                 {
1148                         const char* loopCountName = getLoopCountTypeName((LoopCountType)loopCountType);
1149
1150                         string             groupName = string(loopTypeName) + "_" + string(loopCountName) + "_iterations";
1151                         string             groupDesc = string("Loop tests with ") + loopCountName + " loop counter.";
1152                         TestCaseGroup* group     = new TestCaseGroup(m_context, groupName.c_str(), groupDesc.c_str());
1153                         addChild(group);
1154
1155                         // Generic cases.
1156
1157                         for (int precision = 0; precision < PRECISION_LAST; precision++)
1158                         {
1159                                 const char* precisionName = getPrecisionName((Precision)precision);
1160
1161                                 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_countDataType); dataTypeNdx++)
1162                                 {
1163                                         DataType        loopDataType = s_countDataType[dataTypeNdx];
1164                                         const char* dataTypeName = getDataTypeName(loopDataType);
1165
1166                                         if (precision == PRECISION_LOWP && loopDataType == TYPE_FLOAT)
1167                                                 continue;
1168
1169                                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1170                                         {
1171                                                 ShaderType  shaderType   = s_shaderTypes[shaderTypeNdx];
1172                                                 const char* shaderTypeName = getShaderTypeName((ShaderType)shaderType);
1173                                                 bool            isVertexCase   = (shaderType == SHADERTYPE_VERTEX);
1174
1175                                                 string name = string("basic_") + precisionName + "_" + dataTypeName + "_" + shaderTypeName;
1176                                                 string desc = string(loopTypeName) + " loop with " + precisionName + dataTypeName + " " +
1177                                                                           loopCountName + " iteration count in " + shaderTypeName + " shader.";
1178                                                 group->addChild(createGenericLoopCase(
1179                                                         m_context, m_glslVersion, name.c_str(), desc.c_str(), isVertexCase, (LoopType)loopType,
1180                                                         (LoopCountType)loopCountType, (Precision)precision, loopDataType));
1181                                         }
1182                                 }
1183                         }
1184
1185                         // Special cases.
1186
1187                         for (int loopCase = 0; loopCase < LOOPCASE_LAST; loopCase++)
1188                         {
1189                                 const char* loopCaseName = getLoopCaseName((LoopCase)loopCase);
1190
1191                                 // no-iterations not possible with do-while.
1192                                 if ((loopCase == LOOPCASE_NO_ITERATIONS) && (loopType == LOOPTYPE_DO_WHILE))
1193                                         continue;
1194
1195                                 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1196                                 {
1197                                         ShaderType  shaderType   = s_shaderTypes[shaderTypeNdx];
1198                                         const char* shaderTypeName = getShaderTypeName((ShaderType)shaderType);
1199                                         bool            isVertexCase   = (shaderType == SHADERTYPE_VERTEX);
1200
1201                                         string name = string(loopCaseName) + "_" + shaderTypeName;
1202                                         string desc = string(loopCaseName) + " loop with " + loopTypeName + " iteration count in " +
1203                                                                   shaderTypeName + " shader.";
1204                                         group->addChild(createSpecialLoopCase(m_context, m_glslVersion, name.c_str(), desc.c_str(),
1205                                                                                                                   isVertexCase, (LoopCase)loopCase, (LoopType)loopType,
1206                                                                                                                   (LoopCountType)loopCountType));
1207                                 }
1208                         }
1209                 }
1210         }
1211 }
1212
1213 } // deqp