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