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