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