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