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