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