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