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