glsl-constructor-tests-generator.js (27595B)
1 /* 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 */ 6 7 8 var GLSLConstructorTestsGenerator = (function() { 9 10 var wtu = WebGLTestUtils; 11 12 // Shader code templates 13 var constructorVertexTemplate = [ 14 "attribute vec4 vPosition;", 15 16 "precision mediump int;", 17 "precision mediump float;", 18 19 // Colors used to signal correctness of component values comparison 20 "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);", 21 "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);", 22 23 // Error bound used in comparison of floating point values 24 "$(errorBound)", 25 26 "varying vec4 vColor;", 27 28 "void main() {", 29 " $(argsList)", 30 31 " $(type) v = $(type)($(argsConstr));", 32 33 " if ($(checkCompVals))", 34 " vColor = green;", 35 " else", 36 " vColor = red;", 37 38 " gl_Position = vPosition;", 39 "}" 40 ].join("\n"); 41 42 43 var passThroughColorFragmentShader = [ 44 "precision mediump float;", 45 46 "varying vec4 vColor;", 47 48 "void main() {", 49 " gl_FragColor = vColor;", 50 "}" 51 ].join('\n'); 52 53 54 var constructorFragmentTemplate = [ 55 "precision mediump int;", 56 "precision mediump float;", 57 58 // Colors used to signal correctness of component values comparison 59 "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0); ", 60 "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0); ", 61 62 // Error bound used in comparison of floating point values 63 "$(errorBound)", 64 65 "void main() {", 66 " $(argsList)", 67 68 " $(type) v = $(type)($(argsConstr));", 69 70 " if ($(checkCompVals))", 71 " gl_FragColor = green;", 72 " else", 73 " gl_FragColor = red;", 74 "}" 75 ].join("\n"); 76 77 78 // Coding of the different argument types 79 // s : scalar 80 // v2 : vec2 81 // v3 : vec3 82 // v4 : vec4 83 // m2 : mat2 84 // m3 : mat3 85 // m4 : mat4 86 87 // Returns the dimensions of the type 88 // Count of columns, count of rows 89 function getTypeCodeDimensions(typeCode) { 90 switch (typeCode) { 91 case "s": return [1, 1]; 92 case "v2": return [1, 2]; 93 case "v3": return [1, 3]; 94 case "v4": return [1, 4]; 95 case "m2": return [2, 2]; 96 case "m3": return [3, 3]; 97 case "m4": return [4, 4]; 98 99 default: 100 wtu.error("GLSLConstructorTestsGenerator.getTypeCodeDimensions(), unknown type code"); 101 debugger; 102 } 103 }; 104 105 106 // Returns the component count for the type code 107 function getTypeCodeComponentCount(typeCode) { 108 var dim = getTypeCodeDimensions(typeCode); 109 110 return dim[0] * dim[1]; 111 } 112 113 114 // Returns glsl name of type code 115 function getGLSLBaseTypeName(typeCode) { 116 switch(typeCode) { 117 case "s": return ""; 118 case "v2": return "vec2"; 119 case "v3": return "vec3"; 120 case "v4": return "vec4"; 121 case "m2": return "mat2"; 122 case "m3": return "mat3"; 123 case "m4": return "mat4"; 124 125 default: 126 wtu.error("GLSLConstructorTestsGenerator.getGLSLBaseTypeName(), unknown type code"); 127 debugger; 128 } 129 } 130 131 132 // Returns the scalar glsl type name related to the structured type 133 function getGLSLScalarType(targetType) { 134 switch(targetType[0]) { 135 case 'i': return "int"; 136 case 'b': return "bool"; 137 138 case 'v': 139 case 'm': 140 return "float"; 141 142 default: 143 wtu.error("GLSLConstructorTestsGenerator.getGLSLScalarType(), unknown target type"); 144 debugger; 145 } 146 } 147 148 149 // Returns the scalar prefix for the associated scalar type 150 function getGLSLScalarPrefix(targetType) { 151 switch(targetType[0]) { 152 case 'i': 153 case 'b': 154 return targetType[0]; 155 156 case 'v': 157 case 'm': 158 return ''; 159 160 default: 161 wtu.error("GLSLConstructorTestsGenerator.getGLSLScalarPrefix(), unknown target type"); 162 debugger; 163 } 164 } 165 166 167 // Returns the type for a specified target type and argument type code 168 function getGLSLArgumentType(typeCode, targetType) { 169 var baseType = getGLSLBaseTypeName(typeCode); 170 if (baseType !== "") { 171 if (typeCode[0] === "v") { 172 // Vectors come in different flavours 173 return getGLSLScalarPrefix(targetType) + baseType; 174 } 175 else 176 return baseType; 177 } 178 else 179 return getGLSLScalarType(targetType); 180 } 181 182 183 // Returns the glsl type of the argument components 184 function getGLSLArgumentComponentType(argTypeCode, targetType) { 185 var scalarType; 186 187 if (argTypeCode[0] === "m") { 188 // Matrices are always floats 189 scalarType = "float"; 190 } 191 else 192 scalarType = getGLSLScalarType(targetType); 193 194 return scalarType; 195 } 196 197 198 function getGLSLColumnSize(targetType) { 199 colSize = parseInt(targetType.slice(-1)); 200 201 if (!isNaN(colSize)) 202 return colSize; 203 204 wtu.error("GLSLConstructorTestsGenerator.getGLSLColumnSize(), invalid target type"); 205 debugger; 206 } 207 208 209 // Returns correct string representation of scalar value 210 function getScalarTypeValStr(val, scalarType) { 211 if (val == null) 212 debugger; 213 214 switch (scalarType) { 215 case "float": return val.toFixed(1); 216 case "int": return val; 217 case "bool": return (val === 0) ? "false" : "true"; 218 219 default: 220 wtu.error("GLSLConstructorTestsGenerator.getScalarTypeValStr(), unknown scalar type"); 221 debugger; 222 } 223 } 224 225 226 // Returns true if the glsl type name is a matrix 227 function isGLSLTypeMatrix(type) { 228 return (type.indexOf("mat") !== -1); 229 } 230 231 232 // Returns true if the glsl type name is a vector 233 function isGLSLTypeVector(type) { 234 return (type.indexOf("vec") !== -1); 235 } 236 237 238 // Returns the count of components 239 function getGLSLTypeComponentCount(type) { 240 var colSize = getGLSLColumnSize(type); 241 242 if (isGLSLTypeMatrix(type)) 243 return colSize * colSize; 244 else 245 return colSize; 246 } 247 248 249 // Returns the constructor expression with the components set to a sequence of scalar values 250 // Like vec3(1.0, 2.0, 3.0) 251 function getComponentSequenceConstructorExpression(typeCode, firstCompValue, targetType) { 252 var scalarType = getGLSLArgumentComponentType(typeCode, targetType); 253 254 if (typeCode === "s") { 255 // Scalar 256 return getScalarTypeValStr(firstCompValue, scalarType) + ";"; 257 } 258 else { 259 // Structured typeargTypeCode[0] === "m" 260 compCount = getTypeCodeComponentCount(typeCode); 261 var constrExpParts = new Array(compCount); 262 for (var aa = 0; aa < compCount; ++aa) 263 constrExpParts[aa] = getScalarTypeValStr(firstCompValue + aa, scalarType); 264 265 return getGLSLArgumentType(typeCode, targetType) + "(" + constrExpParts.join(", ") + ");"; 266 } 267 } 268 269 270 // Returns the expression to select a component of the structured type 271 function getComponentSelectorExpStr(targetType, compIx) { 272 if (isGLSLTypeMatrix(targetType)) { 273 var colRowIx = getColRowIndexFromLinearIndex(compIx, getGLSLColumnSize(targetType)); 274 return "v[" + colRowIx.colIx + "][" + colRowIx.rowIx + "]"; 275 } 276 else 277 return "v[" + compIx + "]"; 278 } 279 280 281 // Returns expression which validates the components set by the constructor expression 282 function getComponentValidationExpression(refCompVals, targetType) { 283 // Early out for invalid arguments 284 if (refCompVals.length === 0) 285 return "false"; 286 287 var scalarType = getGLSLScalarType(targetType); 288 var checkComponentValueParts = new Array(refCompVals.length); 289 for (var cc = 0; cc < refCompVals.length; ++cc) { 290 var val_str = getScalarTypeValStr(refCompVals[cc], scalarType); 291 var comp_sel_exp = getComponentSelectorExpStr(targetType, cc); 292 if (scalarType === "float") { 293 // Comparison of floating point values with error bound 294 checkComponentValueParts[cc] = "abs(" + comp_sel_exp + " - " + val_str + ") <= errorBound"; 295 } 296 else { 297 // Simple comparison to expected value 298 checkComponentValueParts[cc] = comp_sel_exp + " == " + val_str; 299 } 300 } 301 302 return checkComponentValueParts.join(" && "); 303 } 304 305 306 // Returns substitution parts to turn the shader template into testable shader code 307 function getTestShaderParts(targetType, argExp, firstCompValue) { 308 // glsl code of declarations of arguments 309 var argsListParts = new Array(argExp.length); 310 311 // glsl code of constructor expression 312 var argsConstrParts = new Array(argExp.length); 313 314 // glsl type expression 315 var typeExpParts = new Array(argExp.length); 316 for (var aa = 0; aa < argExp.length; ++aa) { 317 var typeCode = argExp[aa]; 318 var argCompCount = getTypeCodeComponentCount(typeCode); 319 var argName = "a" + aa; 320 var argType = getGLSLArgumentType(typeCode, targetType); 321 var argConstrExp = argType + " " + argName + " = " + getComponentSequenceConstructorExpression(typeCode, firstCompValue, targetType); 322 323 // Add construction of one argument 324 // Indent if not first argument 325 argsListParts[aa] = ((aa > 0) ? " " : "") + argConstrExp; 326 327 // Add argument name to target type argument list 328 argsConstrParts[aa] = argName; 329 330 // Add type name to type expression 331 typeExpParts[aa] = argType; 332 333 // Increment argument component value so all argument component arguments have a unique value 334 firstCompValue += argCompCount; 335 } 336 337 return { 338 argsList: argsListParts.join("\n") + "\n", 339 argsConstr: argsConstrParts.join(", "), 340 typeExp: targetType + "(" + typeExpParts.join(", ") + ")" 341 }; 342 } 343 344 345 // Utility functions to manipulate the array of reference values 346 347 // Returns array filled with identical values 348 function getArrayWithIdenticalValues(size, val) { 349 var matArray = new Array(size); 350 for (var aa = 0; aa < size; ++aa) 351 matArray[aa] = val; 352 353 return matArray; 354 } 355 356 357 // Returns array filled with increasing values from a specified start value 358 function getArrayWithIncreasingValues(size, start) { 359 var matArray = new Array(size); 360 for (var aa = 0; aa < size; ++aa) 361 matArray[aa] = start + aa; 362 363 return matArray; 364 } 365 366 367 // Utility functions to manipulate the array of reference values if the target type is a matrix 368 369 // Returns an array which is the column order layout of a square matrix where the diagonal is set to a specified value 370 function matCompArraySetDiagonal(matArray, diagVal) { 371 // The entries for the diagonal start at array index 0 and increase 372 // by column size + 1 373 var colSize = Math.round(Math.sqrt(matArray.length)); 374 var dIx = 0; 375 do { 376 matArray[dIx] = diagVal; 377 dIx += (colSize + 1); 378 } 379 while (dIx < colSize * colSize); 380 381 return matArray; 382 } 383 384 385 // Returns an array which contains the values of an identity matrix read out in column order 386 function matCompArrayCreateDiagonalMatrix(colSize, diagVal) { 387 var size = colSize * colSize; 388 var matArray = new Array(size); 389 for (var aa = 0; aa < size; ++aa) 390 matArray[aa] = 0; 391 392 return matCompArraySetDiagonal(matArray, diagVal); 393 } 394 395 396 // Returns the column and row index from the linear index if the components of the matrix are stored in column order in an array 397 // in a one dimensional array in column order 398 function getColRowIndexFromLinearIndex(linIx, colSize) { 399 return { 400 colIx: Math.floor(linIx / colSize), 401 rowIx: linIx % colSize 402 }; 403 } 404 405 406 // Returns the linear index for matrix column and row index for a specified matrix size 407 function getLinearIndexFromColRowIndex(rowColIx, colSize) { 408 return rowColIx.colIx * colSize + rowColIx.rowIx; 409 } 410 411 412 // Returns a matrix set from another matrix 413 function matCompArraySetMatrixFromMatrix(dstColSize, srcMatArray) { 414 // Overwrite components from destination with the source component values at the same col, row coordinates 415 var dstMatArray = matCompArrayCreateDiagonalMatrix(dstColSize, 1); 416 417 var srcColSize = Math.round(Math.sqrt(srcMatArray.length)); 418 419 for (var c_ix = 0; c_ix < srcMatArray.length; ++c_ix) { 420 var srcMatIx = getColRowIndexFromLinearIndex(c_ix, srcColSize); 421 if (srcMatIx.colIx < dstColSize && srcMatIx.rowIx < dstColSize) { 422 // Source matrix coordinates are valid destination matrix coordinates 423 dstMatArray[getLinearIndexFromColRowIndex(srcMatIx, dstColSize)] = srcMatArray[c_ix]; 424 } 425 } 426 427 return dstMatArray; 428 } 429 430 431 // Returns the glsl code to verify if the components are set correctly 432 // and the message to display for the test 433 function getConstructorExpressionInfo(targetType, argExp, firstCompValue) { 434 var argCompCountsSum = 0; 435 var argCompCounts = new Array(argExp.length); 436 for (var aa = 0; aa < argExp.length; ++aa) { 437 argCompCounts[aa] = getTypeCodeComponentCount(argExp[aa]); 438 argCompCountsSum += argCompCounts[aa]; 439 } 440 441 var targetCompCount = getGLSLTypeComponentCount(targetType); 442 443 var refCompVals; 444 var testMsg; 445 var valid; 446 447 if (argCompCountsSum === 0) { 448 // A constructor needs at least one argument 449 refCompVals = []; 450 testMsg = "invalid (no arguments)"; 451 valid = false; 452 } 453 else { 454 if (isGLSLTypeVector(targetType)) { 455 if (argCompCountsSum === 1) { 456 // One scalar argument 457 // Vector constructor with one scalar argument set all components to the same value 458 refCompVals = getArrayWithIdenticalValues(targetCompCount, firstCompValue); 459 testMsg = "valid (all components set to the same value)"; 460 valid = true; 461 } 462 else { 463 // Not one scalar argument 464 if (argCompCountsSum < targetCompCount) { 465 // Not all components set 466 refCompVals = []; 467 testMsg = "invalid (not enough arguments)"; 468 valid = false; 469 } 470 else { 471 // argCompCountsSum >= targetCompCount 472 // All components set 473 var lastArgFirstCompIx = argCompCountsSum - argCompCounts[argCompCounts.length - 1]; 474 475 if (lastArgFirstCompIx < targetCompCount) { 476 // First component of last argument is used 477 refCompVals = getArrayWithIncreasingValues(targetCompCount, firstCompValue); 478 testMsg = "valid"; 479 valid = true; 480 } 481 else { 482 // First component of last argument is not used 483 refCompVals = []; 484 testMsg = "invalid (unused argument)"; 485 valid = false; 486 } 487 } 488 } 489 } 490 else { 491 // Matrix target type 492 if (argCompCountsSum === 1) { 493 // One scalar argument 494 // Matrix constructors with one scalar set all components on the diagonal to the same value 495 // All other components are set to zero 496 refCompVals = matCompArrayCreateDiagonalMatrix(Math.round(Math.sqrt(targetCompCount)), firstCompValue); 497 testMsg = "valid (diagonal components set to the same value, off-diagonal components set to zero)"; 498 valid = true; 499 } 500 else { 501 // Not one scalar argument 502 if (argExp.length === 1 && argExp[0][0] === "m") { 503 // One single matrix argument 504 var dstColSize = getGLSLColumnSize(targetType); 505 refCompVals = matCompArraySetMatrixFromMatrix(dstColSize, getArrayWithIncreasingValues(getTypeCodeComponentCount(argExp[0]), firstCompValue)); 506 testMsg = "valid, components at corresponding col, row indices are set from argument, other components are set from identity matrix"; 507 valid = true; 508 } 509 else { 510 // More than one argument or one argument not of type matrix 511 // Can be treated in the same manner 512 // Arguments can not be of type matrix 513 var matFound = false; 514 for (var aa = 0; aa < argExp.length; ++aa) 515 if (argExp[aa][0] === "m") 516 matFound = true; 517 518 if (matFound) { 519 refCompVals = []; 520 testMsg = "invalid, argument list greater than one contains matrix type"; 521 valid = false; 522 } 523 else { 524 if (argCompCountsSum < targetCompCount) { 525 refCompVals = []; 526 testMsg = "invalid (not enough arguments)"; 527 valid = false; 528 } 529 else { 530 // argCompCountsSum >= targetCompCount 531 // All components set 532 var lastArgFirstCompIx = argCompCountsSum - argCompCounts[argCompCounts.length - 1]; 533 534 if (lastArgFirstCompIx < targetCompCount) { 535 // First component of last argument is used 536 refCompVals = getArrayWithIncreasingValues(targetCompCount, firstCompValue); 537 testMsg = "valid"; 538 valid = true; 539 } 540 else { 541 // First component of last argument is not used 542 refCompVals = []; 543 testMsg = "invalid (unused argument)"; 544 valid = false; 545 } 546 } 547 } 548 } 549 } 550 } 551 } 552 553 // Check if no case is missed 554 if (testMsg == null || valid == null) { 555 wtu.error("GLSLConstructorTestsGenerator.getConstructorExpressionInfo(), info not set"); 556 debugger; 557 } 558 559 return { 560 refCompVals: refCompVals, 561 testMsg: testMsg, 562 valid: valid 563 }; 564 } 565 566 567 // Returns a vertex shader testcase and a fragment shader testcase 568 function getVertexAndFragmentShaderTestCase(targetType, argExp) { 569 var firstCompValue = 0; 570 if (isGLSLTypeMatrix(targetType)) { 571 // Use value different from 0 and 1 572 // 0 and 1 are values used by matrix constructed from a matrix or a single scalar 573 firstCompValue = 2; 574 } 575 576 var argCode = getTestShaderParts (targetType, argExp, firstCompValue); 577 var expInfo = getConstructorExpressionInfo(targetType, argExp, firstCompValue); 578 579 var substitutions = { 580 type: targetType, 581 errorBound: (getGLSLScalarType(targetType) === "float") ? "const float errorBound = 1.0E-5;" : "", 582 argsList: argCode.argsList, 583 argsConstr: argCode.argsConstr, 584 checkCompVals: getComponentValidationExpression(expInfo.refCompVals, targetType) 585 }; 586 587 return [ { 588 // Test constructor argument list in vertex shader 589 vShaderSource: wtu.replaceParams(constructorVertexTemplate, substitutions), 590 vShaderSuccess: expInfo.valid, 591 fShaderSource: passThroughColorFragmentShader, 592 fShaderSuccess: true, 593 linkSuccess: expInfo.valid, 594 passMsg: "Vertex shader : " + argCode.typeExp + ", " + expInfo.testMsg, 595 render: expInfo.valid 596 }, { 597 // Test constructor argument list in fragment shader 598 fShaderSource: wtu.replaceParams(constructorFragmentTemplate, substitutions), 599 fShaderSuccess: expInfo.valid, 600 linkSuccess: expInfo.valid, 601 passMsg: "Fragment shader : " + argCode.typeExp + ", " + expInfo.testMsg, 602 render: expInfo.valid 603 } 604 ]; 605 } 606 607 608 // Incrementing the argument expressions 609 // Utility object which defines the order of incrementing the argument types 610 var typeCodeIncrementer = { 611 s: { typeCode: "v2", order: 0 }, 612 v2: { typeCode: "v3", order: 1 }, 613 v3: { typeCode: "v4", order: 2 }, 614 v4: { typeCode: "m2", order: 3 }, 615 m2: { typeCode: "m3", order: 4 }, 616 m3: { typeCode: "m4", order: 5 }, 617 m4: { typeCode: "s", order: 6 }, 618 first: "s" 619 } 620 621 622 // Returns the next argument sequence 623 function getNextArgumentSequence(inSeq) { 624 var nextSeq; 625 if (inSeq.length === 0) { 626 // Current argument sequence is empty, add first argument 627 nextSeq = [typeCodeIncrementer.first]; 628 } 629 else { 630 nextSeq = new Array(inSeq.length); 631 var overflow = true; 632 for (var aa = 0; aa < inSeq.length; ++aa) { 633 var currArg = inSeq[aa]; 634 if (overflow) { 635 // Increment the current argument type 636 var nextArg = typeCodeIncrementer[currArg].typeCode; 637 nextSeq[aa] = nextArg; 638 overflow = (nextArg === typeCodeIncrementer.first); 639 } 640 else { 641 // Copy remainder of sequence 642 nextSeq[aa] = currArg; 643 } 644 } 645 646 if (overflow) { 647 nextSeq.push(typeCodeIncrementer.first); 648 } 649 } 650 651 return nextSeq; 652 } 653 654 655 // Returns true if two argument expressions are equal 656 function areArgExpEqual(expA, expB) { 657 if (expA.length !== expB.length) 658 return false; 659 660 for (var aa = 0; aa < expA.length; ++aa) 661 if (expA[aa] !== expB[aa]) 662 return false; 663 664 return true; 665 } 666 667 668 // Returns true if first argument expression is smaller 669 // (comes before the second one in iterating order) 670 // compared to the second argument expression 671 function isArgExpSmallerOrEqual(argExpA, argExpB) { 672 var aLen = argExpA.length; 673 var bLen = argExpB.length; 674 if (aLen !== bLen) 675 return (aLen < bLen); 676 677 // Argument type expression lengths are equal 678 for (var aa = aLen - 1; aa >= 0; --aa) { 679 var argA = argExpA[aa]; 680 var argB = argExpB[aa]; 681 682 if (argA !== argB) { 683 var aOrder = typeCodeIncrementer[argA].order; 684 var bOrder = typeCodeIncrementer[argB].order; 685 if (aOrder !== bOrder) 686 return (aOrder < bOrder); 687 } 688 } 689 690 // Argument type expressions are equal 691 return true; 692 } 693 694 695 // Returns the next argument expression from sequence set 696 // Returns null if end is reached 697 function getNextArgumentExpression(testExp, testSet) { 698 var testInterval = testSet[testExp.ix]; 699 700 if (areArgExpEqual(testExp.argExp, testInterval[1])) { 701 // End of current interval reached 702 if (testExp.ix === testSet.length - 1) { 703 // End of set reached 704 return null; 705 } 706 else { 707 // Return first argument expression of next interval 708 var nextIx = testExp.ix + 1; 709 return { ix: nextIx, argExp: testSet[nextIx][0] }; 710 } 711 } 712 else { 713 // Return next expression in current interval 714 return { ix: testExp.ix, argExp: getNextArgumentSequence(testExp.argExp) }; 715 } 716 } 717 718 719 // Returns an array of the parts in the string separated by commas and with the white space trimmed 720 function convertCsvToArray(str) { 721 // Checks type codes in input 722 function checkInput(el, ix, arr) { 723 var typeCode = el.trim(); 724 if (!(typeCode in typeCodeIncrementer) && typeCode !== "first") { 725 wtu.error("GLSLConstructorTestsGenerator.convertCsvToArray(), unknown type code" + typeCode); 726 debugger; 727 } 728 729 arr[ix] = typeCode; 730 } 731 732 var spArr = str.split(","); 733 734 // Convert empty string to empty array 735 if (spArr.length === 1 && spArr[0].trim() === "") 736 spArr = []; 737 738 spArr.forEach(checkInput); 739 740 return spArr; 741 } 742 743 744 // Processes the set of specified test sequences 745 function processInputs(testSequences) { 746 var testSet = new Array(testSequences.length); 747 for (var tt = 0; tt < testSequences.length; ++tt) { 748 var interval = testSequences[tt]; 749 var bounds = interval.split("-"); 750 var begin = convertCsvToArray(bounds[0]); 751 var end = convertCsvToArray(bounds[bounds.length - 1]); 752 753 // Check if interval is valid 754 if (!isArgExpSmallerOrEqual(begin, end)) { 755 wtu.error("GLSLConstructorTestsGenerator.processInputs(), interval not valid"); 756 debugger; 757 } 758 759 testSet[tt] = [ begin, end ]; 760 } 761 762 return testSet; 763 } 764 765 766 /** 767 * Returns list of test cases for vector types 768 * All combinations of arguments up to one unused argument of one component are tested 769 * @param {targetType} Name of target type to test the constructor expressions on 770 * @param {testSet} Set of intervals of argument sequences to test 771 */ 772 function getConstructorTests(targetType, testSequences) { 773 // List of tests to return 774 var testInfos = []; 775 776 // List of argument types 777 var testSet = processInputs(testSequences); 778 var testExp = { ix: 0, argExp: testSet[0][0] }; 779 780 do { 781 // Add one vertex shader test case and one fragment shader test case 782 testInfos = testInfos.concat(getVertexAndFragmentShaderTestCase(targetType, testExp.argExp)); 783 784 // Generate next argument expression 785 testExp = getNextArgumentExpression(testExp, testSet); 786 } 787 while (testExp != null); 788 789 return testInfos; 790 } 791 792 793 // Returns default test argument expression set 794 // For details on input format : see bottom of file 795 function getDefaultTestSet(targetType) { 796 switch(targetType) { 797 case "vec2": 798 case "ivec2": 799 case "bvec2": 800 return [ 801 // No arguments and all single argument expressions 802 " - m4", 803 804 // All two argument expressions with a scalar as second argument 805 "s, s - m4, s", 806 807 // All two arguments expressions with a scalar as first argument 808 "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4", 809 810 // Three argument expression 811 "s, s, s" 812 ]; 813 814 case "vec3": 815 case "ivec3": 816 case "bvec3": 817 return [ 818 // No arguments and all single argument expressions 819 " - m4", 820 821 // All two argument expressions with a scalar as second argument 822 "s, s - m4, s", 823 824 // All two argument expressions with a scalar as first argument 825 "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4", 826 827 // All three argument expressions with two scalars as second and third argument 828 "s, s, s - m4, s, s", 829 830 // All three argument expressions with two scalars as first and second argument 831 "s, s, v2", "s, s, v3", "s, s, v4", "s, s, m2", "s, s, m3", "s, s, m4", 832 833 // Four argument expression 834 "s, s, s, s" 835 ]; 836 837 case "vec4": 838 case "ivec4": 839 case "bvec4": 840 case "mat2": 841 return [ 842 // No arguments and all single argument expressions 843 " - m4", 844 845 // All two argument expressions with a scalar as second argument 846 "s, s - m4, s", 847 848 // All two argument expressions with a scalar as first argument 849 "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4", 850 851 // All three argument expressions with two scalars as second and third argument 852 "s, s, s - m4, s, s", 853 854 // All three argument expressions with two scalars as first and second argument 855 "s, s, v2", "s, s, v3", "s, s, v4", "s, s, m2", "s, s, m3", "s, s, m4", 856 857 // All four argument expressions with three scalars as second, third and fourth argument 858 "s, s, s, s - m4, s, s, s", 859 860 // All four argument expressions with three scalars as first, second and third argument 861 "s, s, s, v2", "s, s, s, v3", "s, s, s, v4", "s, s, s, m2", "s, s, s, m3", "s, s, s, m4", 862 863 // Five argument expression 864 "s, s, s, s, s" 865 ]; 866 867 case "mat3": 868 case "mat4": 869 return [ 870 // No arguments and all single argument expressions 871 " - m4", 872 873 // All two argument expressions with a scalar as second argument 874 "s, s - m4, s", 875 876 // All two argument expressions with a scalar as first argument 877 "s, v2", "s, v3", "s, v4", "s, m2", "s, m3", "s, m4", 878 879 // Several argument sequences 880 "v4, s, v4", "v4, s, v3, v2", "v4, v4, v3, v2", "v4, v4, v4, v4", "v2, v2, v2, v2, v2", "v2, v2, v2, v2, v2, v2, v2, v2", 881 "v3, v3, v3", "v3, v3, v3, s", "v3, v3, v3, v3, v3, s", "v3, v3, v3, v3, v3, s, s", 882 ]; 883 } 884 } 885 886 887 // Return publics 888 return { 889 getConstructorTests: getConstructorTests, 890 getDefaultTestSet: getDefaultTestSet 891 }; 892 893 }()); 894 895 896 // Input is an array of intervals of argument types 897 // The generated test argument sequences are from (including) the lower interval boundary 898 // until (including) the upper boundary 899 // Coding and order of the different argument types : 900 // s : scalar 901 // v2 : vec2 902 // v3 : vec3 903 // v4 : vec4 904 // m2 : mat2 905 // m3 : mat3 906 // m4 : mat4 907 908 // One interval is put in one string 909 // Low and high bound are separated by a dash. 910 // If there is no dash it is regarded as an interval of one expression 911 // The individual argument codes are separated by commas 912 // The individual arguments are incremented from left to right 913 // The left most argument is the one which is incremented first 914 // Once the left most arguments wraps the second argument is increased 915 // Examples : 916 // "s - m4" : All single arguments from scalar up to (including) mat4 917 // "m2, s - m4, s" : All two argument expressions with a matrix argument as first argument and a scalar as second argument 918 // " - m4, m4" : The empty argument, all one arguments and all two argument expressions 919 // "m2, s, v3, m4" : One 4 argument expression : mat2, scalar, vec3, mat4