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