1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Shader loop tests.
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderRenderLoopTests.hpp"
27
28 #include "vktShaderRender.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluShaderUtil.hpp"
31 #include "deStringUtil.hpp"
32
33 #include <map>
34
35 namespace vkt
36 {
37 namespace sr
38 {
39 namespace
40 {
41
getIntUniformName(int number)42 static const char* getIntUniformName (int number)
43 {
44 switch (number)
45 {
46 case 0: return "ui_zero";
47 case 1: return "ui_one";
48 case 2: return "ui_two";
49 case 3: return "ui_three";
50 case 4: return "ui_four";
51 case 5: return "ui_five";
52 case 6: return "ui_six";
53 case 7: return "ui_seven";
54 case 8: return "ui_eight";
55 case 101: return "ui_oneHundredOne";
56 default:
57 DE_ASSERT(false);
58 return "";
59 }
60 }
61
getIntUniformType(int number)62 static BaseUniformType getIntUniformType(int number)
63 {
64 switch (number)
65 {
66 case 1: return UI_ONE;
67 case 2: return UI_TWO;
68 case 3: return UI_THREE;
69 case 4: return UI_FOUR;
70 case 5: return UI_FIVE;
71 case 6: return UI_SIX;
72 case 7: return UI_SEVEN;
73 case 8: return UI_EIGHT;
74 default:
75 DE_ASSERT(false);
76 return UB_FALSE;
77 }
78 }
79
getFloatFractionUniformName(int number)80 static const char* getFloatFractionUniformName (int number)
81 {
82 switch (number)
83 {
84 case 1: return "uf_one";
85 case 2: return "uf_half";
86 case 3: return "uf_third";
87 case 4: return "uf_fourth";
88 case 5: return "uf_fifth";
89 case 6: return "uf_sixth";
90 case 7: return "uf_seventh";
91 case 8: return "uf_eight";
92 default:
93 DE_ASSERT(false);
94 return "";
95 }
96 }
97
getFloatFractionUniformType(int number)98 static BaseUniformType getFloatFractionUniformType(int number)
99 {
100 switch (number)
101 {
102 case 1: return UF_ONE;
103 case 2: return UF_HALF;
104 case 3: return UF_THIRD;
105 case 4: return UF_FOURTH;
106 case 5: return UF_FIFTH;
107 case 6: return UF_SIXTH;
108 case 7: return UF_SEVENTH;
109 case 8: return UF_EIGHTH;
110 default:
111 DE_ASSERT(false);
112 return UB_FALSE;
113 }
114 }
115
116 enum LoopType
117 {
118 LOOPTYPE_FOR = 0,
119 LOOPTYPE_WHILE,
120 LOOPTYPE_DO_WHILE,
121 LOOPTYPE_LAST
122 };
123
getLoopTypeName(LoopType loopType)124 static const char* getLoopTypeName (LoopType loopType)
125 {
126 static const char* s_names[] =
127 {
128 "for",
129 "while",
130 "do_while"
131 };
132
133 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPTYPE_LAST);
134 DE_ASSERT(deInBounds32((int)loopType, 0, LOOPTYPE_LAST));
135 return s_names[(int)loopType];
136 }
137
138 enum LoopCountType
139 {
140 LOOPCOUNT_CONSTANT = 0,
141 LOOPCOUNT_UNIFORM,
142 LOOPCOUNT_DYNAMIC,
143
144 LOOPCOUNT_LAST
145 };
146
147 // Repeated with for, while, do-while. Examples given as 'for' loops.
148 // Repeated for const, uniform, dynamic loops.
149 enum LoopCase
150 {
151 LOOPCASE_EMPTY_BODY = 0, // for (...) { }
152 LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST, // for (...) { break; <body>; }
153 LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST, // for (...) { <body>; break; }
154 LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK, // for (...) { <body>; if (cond) break; }
155 LOOPCASE_SINGLE_STATEMENT, // for (...) statement;
156 LOOPCASE_COMPOUND_STATEMENT, // for (...) { statement; statement; }
157 LOOPCASE_SEQUENCE_STATEMENT, // for (...) statement, statement;
158 LOOPCASE_NO_ITERATIONS, // for (i=0; i<0; i++) ...
159 LOOPCASE_SINGLE_ITERATION, // for (i=0; i<1; i++) ...
160 LOOPCASE_SELECT_ITERATION_COUNT, // for (i=0; i<a?b:c; i++) ...
161 LOOPCASE_CONDITIONAL_CONTINUE, // for (...) { if (cond) continue; }
162 LOOPCASE_UNCONDITIONAL_CONTINUE, // for (...) { <body>; continue; }
163 LOOPCASE_ONLY_CONTINUE, // for (...) { continue; }
164 LOOPCASE_DOUBLE_CONTINUE, // for (...) { if (cond) continue; <body>; $
165 LOOPCASE_CONDITIONAL_BREAK, // for (...) { if (cond) break; }
166 LOOPCASE_UNCONDITIONAL_BREAK, // for (...) { <body>; break; }
167 LOOPCASE_PRE_INCREMENT, // for (...; ++i) { <body>; }
168 LOOPCASE_POST_INCREMENT, // for (...; i++) { <body>; }
169 LOOPCASE_MIXED_BREAK_CONTINUE,
170 LOOPCASE_VECTOR_COUNTER, // for (ivec3 ndx = ...; ndx.x < ndx.y; ndx$
171 LOOPCASE_101_ITERATIONS, // loop for 101 iterations
172 LOOPCASE_SEQUENCE, // two loops in sequence
173 LOOPCASE_NESTED, // two nested loops
174 LOOPCASE_NESTED_SEQUENCE, // two loops in sequence nested inside a th$
175 LOOPCASE_NESTED_TRICKY_DATAFLOW_1, // nested loops with tricky data flow
176 LOOPCASE_NESTED_TRICKY_DATAFLOW_2, // nested loops with tricky data flow
177 LOOPCASE_PRE_FALLTHROUGH, // loop inside switch fallthrough portion
178 LOOPCASE_POST_FALLTHROUGH, // loop inside switch with fallthrough after
179 LOOPCASE_DOWHILE_TRAP, // dowhile loop inside loop which shouldn't loop
180 LOOPCASE_IFBLOCK, // loop inside if block
181 LOOPCASE_ELSEBLOCK, // loop inside else block
182 //LOOPCASE_MULTI_DECLARATION, // for (int i,j,k; ...) ... -- illegal?
183
184 LOOPCASE_LAST
185 };
186
getLoopCaseName(LoopCase loopCase)187 static const char* getLoopCaseName (LoopCase loopCase)
188 {
189 static const char* s_names[] =
190 {
191 "empty_body",
192 "infinite_with_unconditional_break_first",
193 "infinite_with_unconditional_break_last",
194 "infinite_with_conditional_break",
195 "single_statement",
196 "compound_statement",
197 "sequence_statement",
198 "no_iterations",
199 "single_iteration",
200 "select_iteration_count",
201 "conditional_continue",
202 "unconditional_continue",
203 "only_continue",
204 "double_continue",
205 "conditional_break",
206 "unconditional_break",
207 "pre_increment",
208 "post_increment",
209 "mixed_break_continue",
210 "vector_counter",
211 "101_iterations",
212 "sequence",
213 "nested",
214 "nested_sequence",
215 "nested_tricky_dataflow_1",
216 "nested_tricky_dataflow_2",
217 "pre_fallthrough",
218 "post_fallthrough",
219 "dowhile_trap",
220 "ifblock",
221 "elseblock"
222 // "multi_declaration",
223 };
224
225 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPCASE_LAST);
226 DE_ASSERT(deInBounds32((int)loopCase, 0, LOOPCASE_LAST));
227 return s_names[(int)loopCase];
228 }
229
getLoopCountTypeName(LoopCountType countType)230 static const char* getLoopCountTypeName (LoopCountType countType)
231 {
232 static const char* s_names[] =
233 {
234 "constant",
235 "uniform",
236 "dynamic"
237 };
238
239 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == LOOPCOUNT_LAST);
240 DE_ASSERT(deInBounds32((int)countType, 0, LOOPCOUNT_LAST));
241 return s_names[(int)countType];
242 }
243
evalLoop0Iters(ShaderEvalContext& c)244 static void evalLoop0Iters (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
evalLoop1Iters(ShaderEvalContext& c)245 static void evalLoop1Iters (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(1,2,3); }
evalLoop2Iters(ShaderEvalContext& c)246 static void evalLoop2Iters (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(2,3,0); }
evalLoop3Iters(ShaderEvalContext& c)247 static void evalLoop3Iters (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(3,0,1); }
248
getLoopEvalFunc(int numIters)249 static ShaderEvalFunc getLoopEvalFunc (int numIters)
250 {
251 switch (numIters % 4)
252 {
253 case 0: return evalLoop0Iters;
254 case 1: return evalLoop1Iters;
255 case 2: return evalLoop2Iters;
256 case 3: return evalLoop3Iters;
257 }
258
259 DE_FATAL("Invalid loop iteration count.");
260 return NULL;
261 }
262
263 // ShaderLoop case
264
265 class ShaderLoopCase : public ShaderRenderCase
266 {
267 public:
ShaderLoopCase(tcu::TestContext& testCtx, const std::string& name, bool isVertexCase, ShaderEvalFunc evalFunc, UniformSetup* uniformSetup, const std::string& vertexShaderSource, const std::string& fragmentShaderSource)268 ShaderLoopCase (tcu::TestContext& testCtx,
269 const std::string& name,
270 bool isVertexCase,
271 ShaderEvalFunc evalFunc,
272 UniformSetup* uniformSetup,
273 const std::string& vertexShaderSource,
274 const std::string& fragmentShaderSource)
275 : ShaderRenderCase (testCtx, name, isVertexCase, evalFunc, uniformSetup, DE_NULL)
276 {
277 m_vertShaderSource = vertexShaderSource;
278 m_fragShaderSource = fragmentShaderSource;
279 }
280 };
281
282 // Uniform setup tools
283
284 class LoopUniformSetup : public UniformSetup
285 {
286 public:
LoopUniformSetup(std::vector<BaseUniformType>& types)287 LoopUniformSetup (std::vector<BaseUniformType>& types)
288 : m_uniformInformations(types)
289 {}
290
291 virtual void setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const;
292
293 private:
294 std::vector<BaseUniformType> m_uniformInformations;
295 };
296
setup(ShaderRenderCaseInstance& instance, const tcu::Vec4&) const297 void LoopUniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4&) const
298 {
299 for (size_t i = 0; i < m_uniformInformations.size(); i++)
300 {
301 instance.useUniform((deUint32)i, m_uniformInformations[i]);
302 }
303 }
304
305 // Testcase builders
306
createGenericLoopCase(tcu::TestContext& testCtx, const std::string& caseName, bool isVertexCase, LoopType loopType, LoopCountType loopCountType, glu::Precision loopCountPrecision, glu::DataType loopCountDataType)307 static de::MovePtr<ShaderLoopCase> createGenericLoopCase (tcu::TestContext& testCtx,
308 const std::string& caseName,
309 bool isVertexCase,
310 LoopType loopType,
311 LoopCountType loopCountType,
312 glu::Precision loopCountPrecision,
313 glu::DataType loopCountDataType)
314 {
315 std::ostringstream vtx;
316 std::ostringstream frag;
317 std::ostringstream& op = isVertexCase ? vtx : frag;
318
319 vtx << "#version 310 es\n";
320 frag << "#version 310 es\n";
321
322 vtx << "layout(location=0) in highp vec4 a_position;\n";
323 vtx << "layout(location=1) in highp vec4 a_coords;\n";
324 frag << "layout(location=0) out mediump vec4 o_color;\n";
325
326 if (loopCountType == LOOPCOUNT_DYNAMIC)
327 vtx << "layout(location=3) in mediump float a_one;\n";
328
329 if (isVertexCase)
330 {
331 vtx << "layout(location=0) out mediump vec3 v_color;\n";
332 frag << "layout(location=0) in mediump vec3 v_color;\n";
333 }
334 else
335 {
336 vtx << "layout(location=0) out mediump vec4 v_coords;\n";
337 frag << "layout(location=0) in mediump vec4 v_coords;\n";
338
339 if (loopCountType == LOOPCOUNT_DYNAMIC)
340 {
341 vtx << "layout(location=1) out mediump float v_one;\n";
342 frag << "layout(location=1) in mediump float v_one;\n";
343 }
344 }
345
346 const int numLoopIters = 3;
347 const bool isIntCounter = isDataTypeIntOrIVec(loopCountDataType);
348 deUint32 locationCounter = 0;
349 std::vector<BaseUniformType> uniformInformations;
350
351 if (isIntCounter)
352 {
353 if (loopCountType == LOOPCOUNT_UNIFORM || loopCountType == LOOPCOUNT_DYNAMIC)
354 {
355 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff"<< locationCounter <<" {\n";
356 op << " ${COUNTER_PRECISION} int " << getIntUniformName(numLoopIters) << ";\n";
357 op << "};\n";
358 uniformInformations.push_back(getIntUniformType(numLoopIters));
359 locationCounter++;
360 }
361 }
362 else
363 {
364 if (loopCountType == LOOPCOUNT_UNIFORM || loopCountType == LOOPCOUNT_DYNAMIC){
365 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
366 op << " ${COUNTER_PRECISION} float " << getFloatFractionUniformName(numLoopIters) << ";\n";
367 op << "};\n";
368 uniformInformations.push_back(getFloatFractionUniformType(numLoopIters));
369 locationCounter++;
370 }
371
372 if (numLoopIters != 1){
373 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
374 op << " ${COUNTER_PRECISION} float uf_one;\n";
375 op << "};\n";
376 uniformInformations.push_back(UF_ONE);
377 locationCounter++;
378 }
379 }
380
381 vtx << "\n";
382 vtx << "void main()\n";
383 vtx << "{\n";
384 vtx << " gl_Position = a_position;\n";
385
386 frag << "\n";
387 frag << "void main()\n";
388 frag << "{\n";
389
390 if (isVertexCase)
391 vtx << " ${PRECISION} vec4 coords = a_coords;\n";
392 else
393 frag << " ${PRECISION} vec4 coords = v_coords;\n";
394
395
396 if (loopCountType == LOOPCOUNT_DYNAMIC)
397 {
398 if (isIntCounter)
399 {
400 if (isVertexCase)
401 vtx << " ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n";
402 else
403 frag << " ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n";
404 }
405 else
406 {
407 if (isVertexCase)
408 vtx << " ${COUNTER_PRECISION} float one = a_one;\n";
409 else
410 frag << " ${COUNTER_PRECISION} float one = v_one;\n";
411 }
412 }
413
414 // Read array.
415 op << " ${PRECISION} vec4 res = coords;\n";
416
417 // Loop iteration count.
418 std::string iterMaxStr;
419
420 if (isIntCounter)
421 {
422 if (loopCountType == LOOPCOUNT_CONSTANT)
423 iterMaxStr = de::toString(numLoopIters);
424 else if (loopCountType == LOOPCOUNT_UNIFORM)
425 iterMaxStr = getIntUniformName(numLoopIters);
426 else if (loopCountType == LOOPCOUNT_DYNAMIC)
427 iterMaxStr = std::string(getIntUniformName(numLoopIters)) + "*one";
428 else
429 DE_ASSERT(false);
430 }
431 else
432 {
433 if (loopCountType == LOOPCOUNT_CONSTANT)
434 iterMaxStr = "1.0";
435 else if (loopCountType == LOOPCOUNT_UNIFORM)
436 iterMaxStr = "uf_one";
437 else if (loopCountType == LOOPCOUNT_DYNAMIC)
438 iterMaxStr = "uf_one*one";
439 else
440 DE_ASSERT(false);
441 }
442
443 // Loop operations.
444 std::string initValue = isIntCounter ? "0" : "0.05";
445 std::string loopCountDeclStr = "${COUNTER_PRECISION} ${LOOP_VAR_TYPE} ndx = " + initValue;
446 std::string loopCmpStr = ("ndx < " + iterMaxStr);
447 std::string incrementStr;
448 if (isIntCounter)
449 incrementStr = "ndx++";
450 else
451 {
452 if (loopCountType == LOOPCOUNT_CONSTANT)
453 incrementStr = std::string("ndx += ") + de::toString(1.0f / (float)numLoopIters);
454 else if (loopCountType == LOOPCOUNT_UNIFORM)
455 incrementStr = std::string("ndx += ") + getFloatFractionUniformName(numLoopIters);
456 else if (loopCountType == LOOPCOUNT_DYNAMIC)
457 incrementStr = std::string("ndx += ") + getFloatFractionUniformName(numLoopIters) + "*one";
458 else
459 DE_ASSERT(false);
460 }
461
462 // Loop body.
463 std::string loopBody;
464
465 loopBody = " res = res.yzwx + vec4(1.0);\n";
466
467 if (loopType == LOOPTYPE_FOR)
468 {
469 op << " for (" + loopCountDeclStr + "; " + loopCmpStr + "; " + incrementStr + ")\n";
470 op << " {\n";
471 op << loopBody;
472 op << " }\n";
473 }
474 else if (loopType == LOOPTYPE_WHILE)
475 {
476 op << "\t" << loopCountDeclStr + ";\n";
477 op << " while (" + loopCmpStr + ")\n";
478 op << " {\n";
479 op << loopBody;
480 op << "\t\t" + incrementStr + ";\n";
481 op << " }\n";
482 }
483 else if (loopType == LOOPTYPE_DO_WHILE)
484 {
485 op << "\t" << loopCountDeclStr + ";\n";
486 op << " do\n";
487 op << " {\n";
488 op << loopBody;
489 op << "\t\t" + incrementStr + ";\n";
490 op << " } while (" + loopCmpStr + ");\n";
491 }
492 else
493 DE_ASSERT(false);
494
495 op << " res -= vec4(" + de::toString(numLoopIters) + ");\n";
496
497 if (isVertexCase)
498 {
499 vtx << " v_color = res.rgb;\n";
500 frag << " o_color = vec4(v_color.rgb, 1.0);\n";
501 }
502 else
503 {
504 vtx << " v_coords = a_coords;\n";
505 frag << " o_color = vec4(res.rgb, 1.0);\n";
506
507 if (loopCountType == LOOPCOUNT_DYNAMIC)
508 vtx << " v_one = a_one;\n";
509 }
510
511 vtx << "}\n";
512 frag << "}\n";
513
514 // Fill in shader templates.
515 std::map<std::string, std::string> params;
516 params.insert(std::pair<std::string, std::string>("LOOP_VAR_TYPE", getDataTypeName(loopCountDataType)));
517 params.insert(std::pair<std::string, std::string>("PRECISION", "mediump"));
518 params.insert(std::pair<std::string, std::string>("COUNTER_PRECISION", getPrecisionName(loopCountPrecision)));
519
520 tcu::StringTemplate vertTemplate(vtx.str());
521 tcu::StringTemplate fragTemplate(frag.str());
522 std::string vertexShaderSource = vertTemplate.specialize(params);
523 std::string fragmentShaderSource = fragTemplate.specialize(params);
524
525 // Create the case.
526 ShaderEvalFunc evalFunc = getLoopEvalFunc(numLoopIters);
527 UniformSetup* uniformSetup = new LoopUniformSetup(uniformInformations);
528 return de::MovePtr<ShaderLoopCase>(new ShaderLoopCase(testCtx, caseName, isVertexCase, evalFunc, uniformSetup, vertexShaderSource, fragmentShaderSource));
529 }
530
createSpecialLoopCase(tcu::TestContext& testCtx, const std::string& caseName, bool isVertexCase, LoopCase loopCase, LoopType loopType, LoopCountType loopCountType)531 static de::MovePtr<ShaderLoopCase> createSpecialLoopCase (tcu::TestContext& testCtx,
532 const std::string& caseName,
533 bool isVertexCase,
534 LoopCase loopCase,
535 LoopType loopType,
536 LoopCountType loopCountType)
537 {
538 std::ostringstream vtx;
539 std::ostringstream frag;
540 std::ostringstream& op = isVertexCase ? vtx : frag;
541
542 std::vector<BaseUniformType> uniformInformations;
543 deUint32 locationCounter = 0;
544
545 vtx << "#version 310 es\n";
546 frag << "#version 310 es\n";
547
548 vtx << "layout(location=0) in highp vec4 a_position;\n";
549 vtx << "layout(location=1) in highp vec4 a_coords;\n";
550 frag << "layout(location=0) out mediump vec4 o_color;\n";
551
552 if (loopCountType == LOOPCOUNT_DYNAMIC)
553 vtx << "layout(location=3) in mediump float a_one;\n";
554
555 if (isVertexCase)
556 {
557 vtx << "layout(location=0) out mediump vec3 v_color;\n";
558 frag << "layout(location=0) in mediump vec3 v_color;\n";
559 }
560 else
561 {
562 vtx << "layout(location=0) out mediump vec4 v_coords;\n";
563 frag << "layout(location=0) in mediump vec4 v_coords;\n";
564
565 if (loopCountType == LOOPCOUNT_DYNAMIC)
566 {
567 vtx << "layout(location=1) out mediump float v_one;\n";
568 frag << "layout(location=1) in mediump float v_one;\n";
569 }
570 }
571
572 if (loopCase == LOOPCASE_SELECT_ITERATION_COUNT) {
573 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
574 op << " bool ub_true;\n";
575 op << "};\n";
576 uniformInformations.push_back(UB_TRUE);
577 locationCounter++;
578 }
579
580 struct
581 {
582 char const* name;
583 BaseUniformType type;
584 } uniforms[] =
585 {
586 { "ui_zero", UI_ZERO },
587 { "ui_one", UI_ONE },
588 { "ui_two", UI_TWO },
589 { "ui_three", UI_THREE },
590 { "ui_four", UI_FOUR },
591 { "ui_five", UI_FIVE },
592 { "ui_six", UI_SIX },
593 };
594
595 for (int i = 0; i < DE_LENGTH_OF_ARRAY(uniforms); ++i)
596 {
597 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
598 op << " ${COUNTER_PRECISION} int " << uniforms[i].name << ";\n";
599 op << "};\n";
600 uniformInformations.push_back(uniforms[i].type);
601 locationCounter++;
602 }
603
604 if (loopCase == LOOPCASE_101_ITERATIONS) {
605
606 op << "layout(std140, set=0, binding=" << locationCounter << ") uniform buff" << locationCounter << " {\n";
607 op << " ${COUNTER_PRECISION} int ui_oneHundredOne;\n";
608 op << "};\n";
609 uniformInformations.push_back(UI_ONEHUNDREDONE);
610 locationCounter++;
611 }
612
613 int iterCount = 3; // value to use in loop
614 int numIters = 3; // actual number of iterations
615
616 vtx << "\n";
617 vtx << "void main()\n";
618 vtx << "{\n";
619 vtx << " gl_Position = a_position;\n";
620
621 frag << "\n";
622 frag << "void main()\n";
623 frag << "{\n";
624
625 if (loopCountType == LOOPCOUNT_DYNAMIC)
626 {
627 if (isVertexCase)
628 vtx << " ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n";
629 else
630 frag << " ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n";
631 }
632
633 if (isVertexCase)
634 vtx << " ${PRECISION} vec4 coords = a_coords;\n";
635 else
636 frag << " ${PRECISION} vec4 coords = v_coords;\n";
637
638 // Read array.
639 op << " ${PRECISION} vec4 res = coords;\n";
640
641 // Handle all loop types.
642 std::string counterPrecisionStr = "mediump";
643 std::string forLoopStr;
644 std::string whileLoopStr;
645 std::string doWhileLoopPreStr;
646 std::string doWhileLoopPostStr;
647
648 if (loopType == LOOPTYPE_FOR)
649 {
650 switch (loopCase)
651 {
652 case LOOPCASE_EMPTY_BODY:
653 numIters = 0;
654 op << " ${FOR_LOOP} {}\n";
655 break;
656
657 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
658 numIters = 0;
659 op << " for (;;) { break; res = res.yzwx + vec4(1.0); }\n";
660 break;
661
662 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
663 numIters = 1;
664 op << " for (;;) { res = res.yzwx + vec4(1.0); break; }\n";
665 break;
666
667 case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
668 numIters = 2;
669 op << " ${COUNTER_PRECISION} int i = 0;\n";
670 op << " for (;;) { res = res.yzwx + vec4(1.0); if (i == ${ONE}) break; i++; }\n";
671 break;
672
673 case LOOPCASE_SINGLE_STATEMENT:
674 op << " ${FOR_LOOP} res = res.yzwx + vec4(1.0);\n";
675 break;
676
677 case LOOPCASE_COMPOUND_STATEMENT:
678 iterCount = 2;
679 numIters = 2 * iterCount;
680 op << " ${FOR_LOOP} { res = res.yzwx + vec4(1.0); res = res.yzwx + vec4(1.0); }\n";
681 break;
682
683 case LOOPCASE_SEQUENCE_STATEMENT:
684 iterCount = 2;
685 numIters = 2 * iterCount;
686 op << " ${FOR_LOOP} res = res.yzwx + vec4(1.0), res = res.yzwx + vec4(1.0);\n";
687 break;
688
689 case LOOPCASE_NO_ITERATIONS:
690 iterCount = 0;
691 numIters = 0;
692 op << " ${FOR_LOOP} res = res.yzwx + vec4(1.0);\n";
693 break;
694
695 case LOOPCASE_SINGLE_ITERATION:
696 iterCount = 1;
697 numIters = 1;
698 op << " ${FOR_LOOP} res = res.yzwx + vec4(1.0);\n";
699 break;
700
701 case LOOPCASE_SELECT_ITERATION_COUNT:
702 op << " for (int i = 0; i < (ub_true ? ${ITER_COUNT} : 0); i++) res = res.yzwx + vec4(1.0);\n";
703 break;
704
705 case LOOPCASE_CONDITIONAL_CONTINUE:
706 numIters = iterCount - 1;
707 op << " ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx + vec4(1.0); }\n";
708 break;
709
710 case LOOPCASE_UNCONDITIONAL_CONTINUE:
711 op << " ${FOR_LOOP} { res = res.yzwx + vec4(1.0); continue; }\n";
712 break;
713
714 case LOOPCASE_ONLY_CONTINUE:
715 numIters = 0;
716 op << " ${FOR_LOOP} { continue; }\n";
717 break;
718
719 case LOOPCASE_DOUBLE_CONTINUE:
720 numIters = iterCount - 1;
721 op << " ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx + vec4(1.0); continue; }\n";
722 break;
723
724 case LOOPCASE_CONDITIONAL_BREAK:
725 numIters = 2;
726 op << " ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx + vec4(1.0); }\n";
727 break;
728
729 case LOOPCASE_UNCONDITIONAL_BREAK:
730 numIters = 1;
731 op << " ${FOR_LOOP} { res = res.yzwx + vec4(1.0); break; }\n";
732 break;
733
734 case LOOPCASE_PRE_INCREMENT:
735 op << " for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx + vec4(1.0); }\n";
736 break;
737
738 case LOOPCASE_POST_INCREMENT:
739 op << " ${FOR_LOOP} { res = res.yzwx + vec4(1.0); }\n";
740 break;
741
742 case LOOPCASE_MIXED_BREAK_CONTINUE:
743 numIters = 2;
744 iterCount = 5;
745 op << " ${FOR_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx + vec4(1.0); }\n";
746 break;
747
748 case LOOPCASE_VECTOR_COUNTER:
749 op << " for (${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0); i.x < i.z; i.x += i.y) { res = res.yzwx + vec4(1.0); }\n";
750 break;
751
752 case LOOPCASE_101_ITERATIONS:
753 numIters = iterCount = 101;
754 op << " ${FOR_LOOP} res = res.yzwx + vec4(1.0);\n";
755 break;
756
757 case LOOPCASE_SEQUENCE:
758 iterCount = 5;
759 numIters = 5;
760 op << " ${COUNTER_PRECISION} int i;\n";
761 op << " for (i = 0; i < ${TWO}; i++) { res = res.yzwx + vec4(1.0); }\n";
762 op << " for (; i < ${ITER_COUNT}; i++) { res = res.yzwx + vec4(1.0); }\n";
763 break;
764
765 case LOOPCASE_NESTED:
766 numIters = 2 * iterCount;
767 op << " for (${COUNTER_PRECISION} int i = 0; i < ${TWO}; i++)\n";
768 op << " {\n";
769 op << " for (${COUNTER_PRECISION} int j = 0; j < ${ITER_COUNT}; j++)\n";
770 op << " res = res.yzwx + vec4(1.0);\n";
771 op << " }\n";
772 break;
773
774 case LOOPCASE_NESTED_SEQUENCE:
775 numIters = 3 * iterCount;
776 op << " for (${COUNTER_PRECISION} int i = 0; i < ${ITER_COUNT}; i++)\n";
777 op << " {\n";
778 op << " for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
779 op << " res = res.yzwx + vec4(1.0);\n";
780 op << " for (${COUNTER_PRECISION} int j = 0; j < ${ONE}; j++)\n";
781 op << " res = res.yzwx + vec4(1.0);\n";
782 op << " }\n";
783 break;
784
785 case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
786 numIters = 2;
787 op << " ${FOR_LOOP}\n";
788 op << " {\n";
789 op << " res = coords; // ignore outer loop effect \n";
790 op << " for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
791 op << " res = res.yzwx + vec4(1.0);\n";
792 op << " }\n";
793 break;
794
795 case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
796 numIters = iterCount;
797 op << " ${FOR_LOOP}\n";
798 op << " {\n";
799 op << " res = coords.wxyz - vec4(1.0);\n";
800 op << " for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n";
801 op << " res = res.yzwx + vec4(1.0);\n";
802 op << " coords = res;\n";
803 op << " }\n";
804 break;
805
806 case LOOPCASE_PRE_FALLTHROUGH:
807 numIters = iterCount + 1;
808 op << " int j = 3;\n";
809 op << " switch (j)\n";
810 op << " {\n";
811 op << " case 3:\n";
812 op << " res = res.yzwx + vec4(1.0);\n";
813 op << " case 4:\n";
814 op << " ${FOR_LOOP}\n";
815 op << " res = res.yzwx + vec4(1.0);\n";
816 op << " break;\n";
817 op << " }\n";
818 break;
819
820 case LOOPCASE_POST_FALLTHROUGH:
821 numIters = iterCount + 1;
822 op << " int j = 3;\n";
823 op << " switch (j)\n";
824 op << " {\n";
825 op << " case 3:\n";
826 op << " ${FOR_LOOP}\n";
827 op << " res = res.yzwx + vec4(1.0);\n";
828 op << " case 4:\n";
829 op << " res = res.yzwx + vec4(1.0);\n";
830 op << " break;\n";
831 op << " }\n";
832 break;
833
834 case LOOPCASE_DOWHILE_TRAP:
835 numIters = iterCount = 3;
836 op << " ${FOR_LOOP}\n";
837 op << " {\n";
838 op << " do\n";
839 op << " {\n";
840 op << " res = res.yzwx + vec4(1.0);\n";
841 op << " } while (i >= ${THREE});\n";
842 op << " }\n";
843 break;
844
845 case LOOPCASE_IFBLOCK:
846 numIters = iterCount;
847 op << " int j = 3;\n";
848 op << " if (j == ${THREE})\n";
849 op << " {\n";
850 op << " ${FOR_LOOP}\n";
851 op << " res = res.yzwx + vec4(1.0);\n";
852 op << " }\n";
853 op << " else\n";
854 op << " {\n";
855 op << " res = res.yzwx + vec4(1.0);\n";
856 op << " }\n";
857 break;
858
859 case LOOPCASE_ELSEBLOCK:
860 numIters = iterCount;
861 op << " int j = 2;\n";
862 op << " if (j == ${THREE})\n";
863 op << " {\n";
864 op << " res = res.yzwx + vec4(1.0);\n";
865 op << " }\n";
866 op << " else\n";
867 op << " {\n";
868 op << " ${FOR_LOOP}\n";
869 op << " res = res.yzwx + vec4(1.0);\n";
870 op << " }\n";
871 break;
872
873 default:
874 DE_ASSERT(false);
875 }
876
877 if (loopCountType == LOOPCOUNT_CONSTANT)
878 forLoopStr = std::string("for (") + counterPrecisionStr + " int i = 0; i < " + de::toString(iterCount) + "; i++)";
879 else if (loopCountType == LOOPCOUNT_UNIFORM)
880 forLoopStr = std::string("for (") + counterPrecisionStr + " int i = 0; i < " + getIntUniformName(iterCount) + "; i++)";
881 else if (loopCountType == LOOPCOUNT_DYNAMIC)
882 forLoopStr = std::string("for (") + counterPrecisionStr + " int i = 0; i < one*" + getIntUniformName(iterCount) + "; i++)";
883 else
884 DE_ASSERT(false);
885 }
886 else if (loopType == LOOPTYPE_WHILE)
887 {
888 switch (loopCase)
889 {
890 case LOOPCASE_EMPTY_BODY:
891 numIters = 0;
892 op << " ${WHILE_LOOP} {}\n";
893 break;
894
895 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
896 numIters = 0;
897 op << " while (true) { break; res = res.yzwx + vec4(1.0); }\n";
898 break;
899
900 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
901 numIters = 1;
902 op << " while (true) { res = res.yzwx + vec4(1.0); break; }\n";
903 break;
904
905 case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
906 numIters = 2;
907 op << " ${COUNTER_PRECISION} int i = 0;\n";
908 op << " while (true) { res = res.yzwx + vec4(1.0); if (i == ${ONE}) break; i++; }\n";
909 break;
910
911 case LOOPCASE_SINGLE_STATEMENT:
912 op << " ${WHILE_LOOP} res = res.yzwx + vec4(1.0);\n";
913 break;
914
915 case LOOPCASE_COMPOUND_STATEMENT:
916 iterCount = 2;
917 numIters = 2 * iterCount;
918 op << " ${WHILE_LOOP} { res = res.yzwx + vec4(1.0); res = res.yzwx + vec4(1.0); }\n";
919 break;
920
921 case LOOPCASE_SEQUENCE_STATEMENT:
922 iterCount = 2;
923 numIters = 2 * iterCount;
924 op << " ${WHILE_LOOP} res = res.yzwx + vec4(1.0), res = res.yzwx + vec4(1.0);\n";
925 break;
926
927 case LOOPCASE_NO_ITERATIONS:
928 iterCount = 0;
929 numIters = 0;
930 op << " ${WHILE_LOOP} res = res.yzwx + vec4(1.0);\n";
931 break;
932
933 case LOOPCASE_SINGLE_ITERATION:
934 iterCount = 1;
935 numIters = 1;
936 op << " ${WHILE_LOOP} res = res.yzwx + vec4(1.0);\n";
937 break;
938
939 case LOOPCASE_SELECT_ITERATION_COUNT:
940 op << " ${COUNTER_PRECISION} int i = 0;\n";
941 op << " while (i < (ub_true ? ${ITER_COUNT} : 0)) { res = res.yzwx + vec4(1.0); i++; }\n";
942 break;
943
944 case LOOPCASE_CONDITIONAL_CONTINUE:
945 numIters = iterCount - 1;
946 op << " ${WHILE_LOOP} { if (i == ${TWO}) continue; res = res.yzwx + vec4(1.0); }\n";
947 break;
948
949 case LOOPCASE_UNCONDITIONAL_CONTINUE:
950 op << " ${WHILE_LOOP} { res = res.yzwx + vec4(1.0); continue; }\n";
951 break;
952
953 case LOOPCASE_ONLY_CONTINUE:
954 numIters = 0;
955 op << " ${WHILE_LOOP} { continue; }\n";
956 break;
957
958 case LOOPCASE_DOUBLE_CONTINUE:
959 numIters = iterCount - 1;
960 op << " ${WHILE_LOOP} { if (i == ${ONE}) continue; res = res.yzwx + vec4(1.0); continue; }\n";
961 break;
962
963 case LOOPCASE_CONDITIONAL_BREAK:
964 numIters = 2;
965 op << " ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx + vec4(1.0); }\n";
966 break;
967
968 case LOOPCASE_UNCONDITIONAL_BREAK:
969 numIters = 1;
970 op << " ${WHILE_LOOP} { res = res.yzwx + vec4(1.0); break; }\n";
971 break;
972
973 case LOOPCASE_PRE_INCREMENT:
974 numIters = iterCount - 1;
975 op << " ${COUNTER_PRECISION} int i = 0;\n";
976 op << " while (++i < ${ITER_COUNT}) { res = res.yzwx + vec4(1.0); }\n";
977 break;
978
979 case LOOPCASE_POST_INCREMENT:
980 op << " ${COUNTER_PRECISION} int i = 0;\n";
981 op << " while (i++ < ${ITER_COUNT}) { res = res.yzwx + vec4(1.0); }\n";
982 break;
983
984 case LOOPCASE_MIXED_BREAK_CONTINUE:
985 numIters = 2;
986 iterCount = 5;
987 op << " ${WHILE_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx + vec4(1.0); }\n";
988 break;
989
990 case LOOPCASE_VECTOR_COUNTER:
991 op << " ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n";
992 op << " while (i.x < i.z) { res = res.yzwx + vec4(1.0); i.x += i.y; }\n";
993 break;
994
995 case LOOPCASE_101_ITERATIONS:
996 numIters = iterCount = 101;
997 op << " ${WHILE_LOOP} res = res.yzwx + vec4(1.0);\n";
998 break;
999
1000 case LOOPCASE_SEQUENCE:
1001 iterCount = 6;
1002 numIters = iterCount - 1;
1003 op << " ${COUNTER_PRECISION} int i = 0;\n";
1004 op << " while (i++ < ${TWO}) { res = res.yzwx + vec4(1.0); }\n";
1005 op << " while (i++ < ${ITER_COUNT}) { res = res.yzwx + vec4(1.0); }\n"; // \note skips one iteration
1006 break;
1007
1008 case LOOPCASE_NESTED:
1009 numIters = 2 * iterCount;
1010 op << " ${COUNTER_PRECISION} int i = 0;\n";
1011 op << " while (i++ < ${TWO})\n";
1012 op << " {\n";
1013 op << " ${COUNTER_PRECISION} int j = 0;\n";
1014 op << " while (j++ < ${ITER_COUNT})\n";
1015 op << " res = res.yzwx + vec4(1.0);\n";
1016 op << " }\n";
1017 break;
1018
1019 case LOOPCASE_NESTED_SEQUENCE:
1020 numIters = 2 * iterCount;
1021 op << " ${COUNTER_PRECISION} int i = 0;\n";
1022 op << " while (i++ < ${ITER_COUNT})\n";
1023 op << " {\n";
1024 op << " ${COUNTER_PRECISION} int j = 0;\n";
1025 op << " while (j++ < ${ONE})\n";
1026 op << " res = res.yzwx + vec4(1.0);\n";
1027 op << " while (j++ < ${THREE})\n"; // \note skips one iteration
1028 op << " res = res.yzwx + vec4(1.0);\n";
1029 op << " }\n";
1030 break;
1031
1032 case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
1033 numIters = 2;
1034 op << " ${WHILE_LOOP}\n";
1035 op << " {\n";
1036 op << " res = coords; // ignore outer loop effect \n";
1037 op << " ${COUNTER_PRECISION} int j = 0;\n";
1038 op << " while (j++ < ${TWO})\n";
1039 op << " res = res.yzwx + vec4(1.0);\n";
1040 op << " }\n";
1041 break;
1042
1043 case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
1044 numIters = iterCount;
1045 op << " ${WHILE_LOOP}\n";
1046 op << " {\n";
1047 op << " res = coords.wxyz - vec4(1.0);\n";
1048 op << " ${COUNTER_PRECISION} int j = 0;\n";
1049 op << " while (j++ < ${TWO})\n";
1050 op << " res = res.yzwx + vec4(1.0);\n";
1051 op << " coords = res;\n";
1052 op << " }\n";
1053 break;
1054
1055 case LOOPCASE_PRE_FALLTHROUGH:
1056 numIters = iterCount + 1;
1057 op << " int j = 3;\n";
1058 op << " switch (j)\n";
1059 op << " {\n";
1060 op << " case 3:\n";
1061 op << " res = res.yzwx + vec4(1.0);\n";
1062 op << " case 4:\n";
1063 op << " ${WHILE_LOOP}\n";
1064 op << " res = res.yzwx + vec4(1.0);\n";
1065 op << " break;\n";
1066 op << " }\n";
1067 break;
1068
1069 case LOOPCASE_POST_FALLTHROUGH:
1070 numIters = iterCount + 1;
1071 op << " int j = 3;\n";
1072 op << " switch (j)\n";
1073 op << " {\n";
1074 op << " case 3:\n";
1075 op << " ${WHILE_LOOP}\n";
1076 op << " res = res.yzwx + vec4(1.0);\n";
1077 op << " case 4:\n";
1078 op << " res = res.yzwx + vec4(1.0);\n";
1079 op << " break;\n";
1080 op << " }\n";
1081 break;
1082
1083 case LOOPCASE_DOWHILE_TRAP:
1084 numIters = iterCount = 3;
1085 op << " ${WHILE_LOOP}\n";
1086 op << " {\n";
1087 op << " do\n";
1088 op << " {\n";
1089 op << " res = res.yzwx + vec4(1.0);\n";
1090 op << " } while (i > ${THREE});\n";
1091 op << " }\n";
1092 break;
1093
1094 case LOOPCASE_IFBLOCK:
1095 numIters = iterCount;
1096 op << " int j = 3;\n";
1097 op << " if (j == ${THREE})\n";
1098 op << " {\n";
1099 op << " ${WHILE_LOOP}\n";
1100 op << " res = res.yzwx + vec4(1.0);\n";
1101 op << " }\n";
1102 op << " else\n";
1103 op << " {\n";
1104 op << " res = res.yzwx + vec4(1.0);\n";
1105 op << " }\n";
1106 break;
1107
1108 case LOOPCASE_ELSEBLOCK:
1109 numIters = iterCount;
1110 op << " int j = 2;\n";
1111 op << " if (j == ${THREE})\n";
1112 op << " {\n";
1113 op << " res = res.yzwx + vec4(1.0);\n";
1114 op << " }\n";
1115 op << " else\n";
1116 op << " {\n";
1117 op << " ${WHILE_LOOP}\n";
1118 op << " res = res.yzwx + vec4(1.0);\n";
1119 op << " }\n";
1120 break;
1121
1122 default:
1123 DE_ASSERT(false);
1124 }
1125
1126 if (loopCountType == LOOPCOUNT_CONSTANT)
1127 whileLoopStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + " while(i++ < " + de::toString(iterCount) + ")";
1128 else if (loopCountType == LOOPCOUNT_UNIFORM)
1129 whileLoopStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + " while(i++ < " + getIntUniformName(iterCount) + ")";
1130 else if (loopCountType == LOOPCOUNT_DYNAMIC)
1131 whileLoopStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + " while(i++ < one*" + getIntUniformName(iterCount) + ")";
1132 else
1133 DE_ASSERT(false);
1134 }
1135 else
1136 {
1137 DE_ASSERT(loopType == LOOPTYPE_DO_WHILE);
1138
1139 switch (loopCase)
1140 {
1141 case LOOPCASE_EMPTY_BODY:
1142 numIters = 0;
1143 op << " ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n";
1144 break;
1145
1146 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
1147 numIters = 0;
1148 op << " do { break; res = res.yzwx + vec4(1.0); } while (true);\n";
1149 break;
1150
1151 case LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
1152 numIters = 1;
1153 op << " do { res = res.yzwx + vec4(1.0); break; } while (true);\n";
1154 break;
1155
1156 case LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
1157 numIters = 2;
1158 op << " ${COUNTER_PRECISION} int i = 0;\n";
1159 op << " do { res = res.yzwx + vec4(1.0); if (i == ${ONE}) break; i++; } while (true);\n";
1160 break;
1161
1162 case LOOPCASE_SINGLE_STATEMENT:
1163 op << " ${DO_WHILE_PRE} res = res.yzwx + vec4(1.0); ${DO_WHILE_POST}\n";
1164 break;
1165
1166 case LOOPCASE_COMPOUND_STATEMENT:
1167 iterCount = 2;
1168 numIters = 2 * iterCount;
1169 op << " ${DO_WHILE_PRE} { res = res.yzwx + vec4(1.0); res = res.yzwx + vec4(1.0); } ${DO_WHILE_POST}\n";
1170 break;
1171
1172 case LOOPCASE_SEQUENCE_STATEMENT:
1173 iterCount = 2;
1174 numIters = 2 * iterCount;
1175 op << " ${DO_WHILE_PRE} res = res.yzwx + vec4(1.0), res = res.yzwx + vec4(1.0); ${DO_WHILE_POST}\n";
1176 break;
1177
1178 case LOOPCASE_NO_ITERATIONS:
1179 DE_ASSERT(false);
1180 break;
1181
1182 case LOOPCASE_SINGLE_ITERATION:
1183 iterCount = 1;
1184 numIters = 1;
1185 op << " ${DO_WHILE_PRE} res = res.yzwx + vec4(1.0); ${DO_WHILE_POST}\n";
1186 break;
1187
1188 case LOOPCASE_SELECT_ITERATION_COUNT:
1189 op << " ${COUNTER_PRECISION} int i = 0;\n";
1190 op << " do { res = res.yzwx + vec4(1.0); } while (++i < (ub_true ? ${ITER_COUNT} : 0));\n";
1191 break;
1192
1193 case LOOPCASE_CONDITIONAL_CONTINUE:
1194 numIters = iterCount - 1;
1195 op << " ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx + vec4(1.0); } ${DO_WHILE_POST}\n";
1196 break;
1197
1198 case LOOPCASE_UNCONDITIONAL_CONTINUE:
1199 op << " ${DO_WHILE_PRE} { res = res.yzwx + vec4(1.0); continue; } ${DO_WHILE_POST}\n";
1200 break;
1201
1202 case LOOPCASE_ONLY_CONTINUE:
1203 numIters = 0;
1204 op << " ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n";
1205 break;
1206
1207 case LOOPCASE_DOUBLE_CONTINUE:
1208 numIters = iterCount - 1;
1209 op << " ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx + vec4(1.0); continue; } ${DO_WHILE_POST}\n";
1210 break;
1211
1212 case LOOPCASE_CONDITIONAL_BREAK:
1213 numIters = 2;
1214 op << " ${DO_WHILE_PRE} { res = res.yzwx + vec4(1.0); if (i == ${ONE}) break; } ${DO_WHILE_POST}\n";
1215 break;
1216
1217 case LOOPCASE_UNCONDITIONAL_BREAK:
1218 numIters = 1;
1219 op << " ${DO_WHILE_PRE} { res = res.yzwx + vec4(1.0); break; } ${DO_WHILE_POST}\n";
1220 break;
1221
1222 case LOOPCASE_PRE_INCREMENT:
1223 op << " ${COUNTER_PRECISION} int i = 0;\n";
1224 op << " do { res = res.yzwx + vec4(1.0); } while (++i < ${ITER_COUNT});\n";
1225 break;
1226
1227 case LOOPCASE_POST_INCREMENT:
1228 numIters = iterCount + 1;
1229 op << " ${COUNTER_PRECISION} int i = 0;\n";
1230 op << " do { res = res.yzwx + vec4(1.0); } while (i++ < ${ITER_COUNT});\n";
1231 break;
1232
1233 case LOOPCASE_MIXED_BREAK_CONTINUE:
1234 numIters = 2;
1235 iterCount = 5;
1236 op << " ${DO_WHILE_PRE} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx + vec4(1.0); } ${DO_WHILE_POST}\n";
1237 break;
1238
1239 case LOOPCASE_VECTOR_COUNTER:
1240 op << " ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n";
1241 op << " do { res = res.yzwx + vec4(1.0); } while ((i.x += i.y) < i.z);\n";
1242 break;
1243
1244 case LOOPCASE_101_ITERATIONS:
1245 numIters = iterCount = 101;
1246 op << " ${DO_WHILE_PRE} res = res.yzwx + vec4(1.0); ${DO_WHILE_POST}\n";
1247 break;
1248
1249 case LOOPCASE_SEQUENCE:
1250 iterCount = 5;
1251 numIters = 5;
1252 op << " ${COUNTER_PRECISION} int i = 0;\n";
1253 op << " do { res = res.yzwx + vec4(1.0); } while (++i < ${TWO});\n";
1254 op << " do { res = res.yzwx + vec4(1.0); } while (++i < ${ITER_COUNT});\n";
1255 break;
1256
1257 case LOOPCASE_NESTED:
1258 numIters = 2 * iterCount;
1259 op << " ${COUNTER_PRECISION} int i = 0;\n";
1260 op << " do\n";
1261 op << " {\n";
1262 op << " ${COUNTER_PRECISION} int j = 0;\n";
1263 op << " do\n";
1264 op << " res = res.yzwx + vec4(1.0);\n";
1265 op << " while (++j < ${ITER_COUNT});\n";
1266 op << " } while (++i < ${TWO});\n";
1267 break;
1268
1269 case LOOPCASE_NESTED_SEQUENCE:
1270 numIters = 3 * iterCount;
1271 op << " ${COUNTER_PRECISION} int i = 0;\n";
1272 op << " do\n";
1273 op << " {\n";
1274 op << " ${COUNTER_PRECISION} int j = 0;\n";
1275 op << " do\n";
1276 op << " res = res.yzwx + vec4(1.0);\n";
1277 op << " while (++j < ${TWO});\n";
1278 op << " do\n";
1279 op << " res = res.yzwx + vec4(1.0);\n";
1280 op << " while (++j < ${THREE});\n";
1281 op << " } while (++i < ${ITER_COUNT});\n";
1282 break;
1283
1284 case LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
1285 numIters = 2;
1286 op << " ${DO_WHILE_PRE}\n";
1287 op << " {\n";
1288 op << " res = coords; // ignore outer loop effect \n";
1289 op << " ${COUNTER_PRECISION} int j = 0;\n";
1290 op << " do\n";
1291 op << " res = res.yzwx + vec4(1.0);\n";
1292 op << " while (++j < ${TWO});\n";
1293 op << " } ${DO_WHILE_POST}\n";
1294 break;
1295
1296 case LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
1297 numIters = iterCount;
1298 op << " ${DO_WHILE_PRE}\n";
1299 op << " {\n";
1300 op << " res = coords.wxyz - vec4(1.0);\n";
1301 op << " ${COUNTER_PRECISION} int j = 0;\n";
1302 op << " while (j++ < ${TWO})\n";
1303 op << " res = res.yzwx + vec4(1.0);\n";
1304 op << " coords = res;\n";
1305 op << " } ${DO_WHILE_POST}\n";
1306 break;
1307
1308 case LOOPCASE_PRE_FALLTHROUGH:
1309 numIters = iterCount + 1;
1310 op << " int j = 3;\n";
1311 op << " switch (j)\n";
1312 op << " {\n";
1313 op << " case 3:\n";
1314 op << " res = res.yzwx + vec4(1.0);\n";
1315 op << " case 4:\n";
1316 op << " ${DO_WHILE_PRE}\n";
1317 op << " {\n";
1318 op << " res = res.yzwx + vec4(1.0);\n";
1319 op << " } ${DO_WHILE_POST}\n";
1320 op << " break;\n";
1321 op << " }\n";
1322 break;
1323
1324 case LOOPCASE_POST_FALLTHROUGH:
1325 numIters = iterCount + 1;
1326 op << " int j = 3;\n";
1327 op << " switch (j)\n";
1328 op << " {\n";
1329 op << " case 3:\n";
1330 op << " ${DO_WHILE_PRE}\n";
1331 op << " {\n";
1332 op << " res = res.yzwx + vec4(1.0);\n";
1333 op << " } ${DO_WHILE_POST}\n";
1334 op << " case 4:\n";
1335 op << " res = res.yzwx + vec4(1.0);\n";
1336 op << " break;\n";
1337 op << " }\n";
1338 break;
1339
1340 case LOOPCASE_DOWHILE_TRAP:
1341 numIters = iterCount = 3;
1342 op << " ${DO_WHILE_PRE}\n";
1343 op << " {\n";
1344 op << " do\n";
1345 op << " {\n";
1346 op << " res = res.yzwx + vec4(1.0);\n";
1347 op << " } while (i >= ${THREE});\n";
1348 op << " } ${DO_WHILE_POST}\n";
1349 break;
1350
1351 case LOOPCASE_IFBLOCK:
1352 numIters = iterCount;
1353 op << " int j = 3;\n";
1354 op << " if (j == ${THREE})\n";
1355 op << " {\n";
1356 op << " ${DO_WHILE_PRE}\n";
1357 op << " {\n";
1358 op << " res = res.yzwx + vec4(1.0);\n";
1359 op << " } ${DO_WHILE_POST}\n";
1360 op << " }\n";
1361 op << " else\n";
1362 op << " {\n";
1363 op << " res = res.yzwx + vec4(1.0);\n";
1364 op << " }\n";
1365 break;
1366
1367 case LOOPCASE_ELSEBLOCK:
1368 numIters = iterCount;
1369 op << " int j = 2;\n";
1370 op << " if (j == ${THREE})\n";
1371 op << " {\n";
1372 op << " res = res.yzwx + vec4(1.0);\n";
1373 op << " }\n";
1374 op << " else\n";
1375 op << " {\n";
1376 op << " ${DO_WHILE_PRE}\n";
1377 op << " {\n";
1378 op << " res = res.yzwx + vec4(1.0);\n";
1379 op << " } ${DO_WHILE_POST}\n";
1380 op << " }\n";
1381 break;
1382
1383 default:
1384 DE_ASSERT(false);
1385 }
1386
1387 doWhileLoopPreStr = std::string("\t") + counterPrecisionStr + " int i = 0;\n" + "\tdo ";
1388 if (loopCountType == LOOPCOUNT_CONSTANT)
1389 doWhileLoopPostStr = std::string(" while (++i < ") + de::toString(iterCount) + ");\n";
1390 else if (loopCountType == LOOPCOUNT_UNIFORM)
1391 doWhileLoopPostStr = std::string(" while (++i < ") + getIntUniformName(iterCount) + ");\n";
1392 else if (loopCountType == LOOPCOUNT_DYNAMIC)
1393 doWhileLoopPostStr = std::string(" while (++i < one*") + getIntUniformName(iterCount) + ");\n";
1394 else
1395 DE_ASSERT(false);
1396 }
1397
1398 // Shader footers.
1399 op << " res -= vec4(${NUM_ITERS});\n";
1400
1401 if (isVertexCase)
1402 {
1403 vtx << " v_color = res.rgb;\n";
1404 frag << " o_color = vec4(v_color.rgb, 1.0);\n";
1405 }
1406 else
1407 {
1408 vtx << " v_coords = a_coords;\n";
1409 frag << " o_color = vec4(res.rgb, 1.0);\n";
1410
1411 if (loopCountType == LOOPCOUNT_DYNAMIC)
1412 vtx << " v_one = a_one;\n";
1413 }
1414
1415 vtx << "}\n";
1416 frag << "}\n";
1417
1418 // Constants.
1419 std::string oneStr;
1420 std::string twoStr;
1421 std::string threeStr;
1422 std::string iterCountStr;
1423 std::string numItersStr;
1424
1425 numItersStr = de::toString(numIters);
1426
1427 if (loopCountType == LOOPCOUNT_CONSTANT)
1428 {
1429 oneStr = "1";
1430 twoStr = "2";
1431 threeStr = "3";
1432 iterCountStr = de::toString(iterCount);
1433 }
1434 else if (loopCountType == LOOPCOUNT_UNIFORM)
1435 {
1436 oneStr = "ui_one";
1437 twoStr = "ui_two";
1438 threeStr = "ui_three";
1439 iterCountStr = getIntUniformName(iterCount);
1440 }
1441 else if (loopCountType == LOOPCOUNT_DYNAMIC)
1442 {
1443 oneStr = "one*ui_one";
1444 twoStr = "one*ui_two";
1445 threeStr = "one*ui_three";
1446 iterCountStr = std::string("one*") + getIntUniformName(iterCount);
1447 }
1448 else DE_ASSERT(false);
1449
1450 // Fill in shader templates.
1451 std::map<std::string, std::string> params;
1452 params.insert(std::pair<std::string, std::string>("PRECISION", "mediump"));
1453 params.insert(std::pair<std::string, std::string>("ITER_COUNT", iterCountStr));
1454 params.insert(std::pair<std::string, std::string>("NUM_ITERS", numItersStr));
1455 params.insert(std::pair<std::string, std::string>("COUNTER_PRECISION", counterPrecisionStr));
1456 params.insert(std::pair<std::string, std::string>("FOR_LOOP", forLoopStr));
1457 params.insert(std::pair<std::string, std::string>("WHILE_LOOP", whileLoopStr));
1458 params.insert(std::pair<std::string, std::string>("DO_WHILE_PRE", doWhileLoopPreStr));
1459 params.insert(std::pair<std::string, std::string>("DO_WHILE_POST", doWhileLoopPostStr));
1460 params.insert(std::pair<std::string, std::string>("ONE", oneStr));
1461 params.insert(std::pair<std::string, std::string>("TWO", twoStr));
1462 params.insert(std::pair<std::string, std::string>("THREE", threeStr));
1463
1464 tcu::StringTemplate vertTemplate(vtx.str());
1465 tcu::StringTemplate fragTemplate(frag.str());
1466 std::string vertexShaderSource = vertTemplate.specialize(params);
1467 std::string fragmentShaderSource = fragTemplate.specialize(params);
1468
1469 // Create the case.
1470 UniformSetup* uniformSetup = new LoopUniformSetup(uniformInformations);
1471 ShaderEvalFunc evalFunc = getLoopEvalFunc(numIters);
1472 return de::MovePtr<ShaderLoopCase>(new ShaderLoopCase(testCtx, caseName, isVertexCase, evalFunc, uniformSetup, vertexShaderSource, fragmentShaderSource));
1473 }
1474
1475 class ShaderLoopTests : public tcu::TestCaseGroup
1476 {
1477 public:
1478 ShaderLoopTests (tcu::TestContext& testCtx);
1479 virtual ~ShaderLoopTests (void);
1480
1481 virtual void init (void);
1482
1483 private:
1484 ShaderLoopTests (const ShaderLoopTests&); // not allowed!
1485 ShaderLoopTests& operator= (const ShaderLoopTests&); // not allowed!
1486 };
1487
ShaderLoopTests(tcu::TestContext& testCtx)1488 ShaderLoopTests::ShaderLoopTests(tcu::TestContext& testCtx)
1489 : TestCaseGroup(testCtx, "loops")
1490 {
1491 }
1492
~ShaderLoopTests(void)1493 ShaderLoopTests::~ShaderLoopTests (void)
1494 {
1495 }
1496
init(void)1497 void ShaderLoopTests::init (void)
1498 {
1499 // Loop cases.
1500
1501 static const glu::ShaderType s_shaderTypes[] =
1502 {
1503 glu::SHADERTYPE_VERTEX,
1504 glu::SHADERTYPE_FRAGMENT
1505 };
1506
1507 static const glu::DataType s_countDataType[] =
1508 {
1509 glu::TYPE_INT,
1510 glu::TYPE_FLOAT
1511 };
1512
1513 TestCaseGroup* genericGroup = new TestCaseGroup(m_testCtx, "generic");
1514 TestCaseGroup* specialGroup = new TestCaseGroup(m_testCtx, "special");
1515 addChild(genericGroup);
1516 addChild(specialGroup);
1517
1518 for (int loopType = 0; loopType < LOOPTYPE_LAST; loopType++)
1519 {
1520 const char* loopTypeName = getLoopTypeName((LoopType)loopType);
1521
1522 for (int loopCountType = 0; loopCountType < LOOPCOUNT_LAST; loopCountType++)
1523 {
1524 const char* loopCountName = getLoopCountTypeName((LoopCountType)loopCountType);
1525
1526 std::string groupName = std::string(loopTypeName) + "_" + std::string(loopCountName) + "_iterations";
1527 std::string groupDesc = std::string("Loop tests with ") + loopCountName + " loop counter.";
1528 TestCaseGroup* genericSubGroup = new TestCaseGroup(m_testCtx, groupName.c_str());
1529 TestCaseGroup* specialSubGroup = new TestCaseGroup(m_testCtx, groupName.c_str());
1530 genericGroup->addChild(genericSubGroup);
1531 specialGroup->addChild(specialSubGroup);
1532
1533 // Generic cases.
1534
1535 for (int precision = glu::PRECISION_MEDIUMP; precision < glu::PRECISION_LAST; precision++)
1536 {
1537 const char* precisionName = getPrecisionName((glu::Precision)precision);
1538
1539 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_countDataType); dataTypeNdx++)
1540 {
1541 glu::DataType loopDataType = s_countDataType[dataTypeNdx];
1542 const char* dataTypeName = getDataTypeName(loopDataType);
1543
1544 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1545 {
1546 glu::ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1547 const char* shaderTypeName = getShaderTypeName(shaderType);
1548 bool isVertexCase = (shaderType == glu::SHADERTYPE_VERTEX);
1549
1550 std::string testName = std::string("basic_") + precisionName + "_" + dataTypeName + "_" + shaderTypeName;
1551 de::MovePtr<ShaderLoopCase> testCase(createGenericLoopCase(m_testCtx, testName.c_str(), isVertexCase, (LoopType)loopType, (LoopCountType)loopCountType, (glu::Precision)precision, loopDataType));
1552 genericSubGroup->addChild(testCase.release());
1553 }
1554 }
1555 }
1556
1557 // Special cases.
1558
1559 for (int loopCase = 0; loopCase < LOOPCASE_LAST; loopCase++)
1560 {
1561 const char* loopCaseName = getLoopCaseName((LoopCase)loopCase);
1562
1563 // no-iterations not possible with do-while.
1564 if ((loopCase == LOOPCASE_NO_ITERATIONS) && (loopType == LOOPTYPE_DO_WHILE))
1565 continue;
1566
1567 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1568 {
1569 glu::ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1570 const char* shaderTypeName = getShaderTypeName(shaderType);
1571 bool isVertexCase = (shaderType == glu::SHADERTYPE_VERTEX);
1572
1573 std::string name = std::string(loopCaseName) + "_" + shaderTypeName;
1574 de::MovePtr<ShaderLoopCase> testCase(createSpecialLoopCase(m_testCtx, name.c_str(), isVertexCase, (LoopCase)loopCase, (LoopType)loopType, (LoopCountType)loopCountType));
1575 specialSubGroup->addChild(testCase.release());
1576 }
1577 }
1578 }
1579 }
1580 }
1581
1582 } // anonymous
1583
createLoopTests(tcu::TestContext& testCtx)1584 tcu::TestCaseGroup* createLoopTests (tcu::TestContext& testCtx)
1585 {
1586 return new ShaderLoopTests(testCtx);
1587 }
1588
1589
1590 } // sr
1591 } // vkt
1592