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