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