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