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