2 ** Copyright (c) 2014 The Khronos Group Inc.
4 ** Permission is hereby granted, free of charge, to any person obtaining a
5 ** copy of this software and/or associated documentation files (the
6 ** "Materials"), to deal in the Materials without restriction, including
7 ** without limitation the rights to use, copy, modify, merge, publish,
8 ** distribute, sublicense, and/or sell copies of the Materials, and to
9 ** permit persons to whom the Materials are furnished to do so, subject to
10 ** the following conditions:
12 ** The above copyright notice and this permission notice shall be included
13 ** in all copies or substantial portions of the Materials.
15 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
25 var GLSLConstructorTestsGenerator = (function() {
28 var MAX_COMP_COUNT = 4;
29 var MAX_ARG_COUNT = MAX_COMP_COUNT + 1;
30 var UNUSED_EXP_COUNT = 1;
33 var EXP_INVALID_NO_ARGS = 1;
34 var EXP_INVALID_NOT_ENOUGH_COMPS = 2;
35 var EXP_INVALID_TOO_MANY_ARGS = 3;
37 var wtu = WebGLTestUtils;
39 // Shader code templates
40 var vectorConstructorVertexTemplate = [
41 "precision mediump int;",
42 "precision mediump float;",
43 "varying vec4 v_color;",
48 " $(vecType) v = $(vecType)($(arg0)$(arg1)$(arg2)$(arg3)$(arg4)); ",
49 " gl_Position = vec4(v$(filler));",
54 var vectorConstructorFragmentTemplate = [
55 "precision mediump int;",
56 "precision mediump float;",
61 " $(vecType) v = $(vecType)($(arg0)$(arg1)$(arg2)$(arg3)$(arg4)); ",
63 " gl_FragColor = vec4(v$(filler));",
68 // Returns correct string representation of scalar value
69 function getScalarTypeValStr(val, scalarType) {
72 return val.toFixed(1);
78 return (val === 0) ? "true" : "false";
86 // Returns a string which is the constructor expression in which every component is set to a scalar value
87 function getArgumentValue(compCount, vecName, argCompValue, scalarType) {
88 if (compCount === 1) {
90 return getScalarTypeValStr(argCompValue, scalarType);
95 // Create substitution object
100 for (var aa = 0; aa < MAX_COMP_COUNT; ++aa) {
101 var argName = "arg" + aa;
103 subst[argName] = getScalarTypeValStr(argCompValue + aa, scalarType) + ((aa < compCount - 1) ? ", " : "");
108 return wtu.replaceParams(
109 "$(vecType)($(arg0)$(arg1)$(arg2)$(arg3))",
116 // Returns comma separated sequence of numbers so constructor expression has always 4 components
117 function getVec4Filler(compCount) {
119 for (var ff = compCount; ff < MAX_COMP_COUNT; ++ff)
126 // Returns substitution object to turn the shader template into testable shader code
127 function getSubstitutions(vecBaseType, compCount, scalarType, argCompCounts) {
129 var argCompValue = 0;
131 vecType: vecBaseType + compCount,
132 filler: getVec4Filler(compCount)
135 for (var aa = 0; aa < MAX_ARG_COUNT; ++aa) {
137 var argCompCount = argCompCounts[aa];
138 if (argCompCount !== undefined) {
139 var argName = "a" + aa;
140 var argVecType = vecBaseType + argCompCount;
141 var argExp = wtu.replaceParams("$(argType) $(argName) = $(argVal);", {
142 argType: ((argCompCount === 1) ? scalarType : argVecType),
144 argVal: getArgumentValue(argCompCount, argVecType, argCompValue, scalarType)
146 argList += ((aa > 0) ? " " : "") + argExp + "\n";
148 // Name of argument with separating comma (if not last argument)
149 arg = argName + ((aa === argCompCounts.length - 1) ? "" : ", ");
151 // Increment argument component value so all argument component arguments have a unique value
152 argCompValue += argCompCount;
155 subst["arg" + aa] = arg;
157 subst["argList"] = argList;
163 // Returns the constructor expression with only type names
164 // Like : vec3(float, vec2)
165 function getConstructorTypeExpression(vecBaseType, compCount, scalarType, argCompCounts) {
166 // Create substitution object
168 vecType: vecBaseType + compCount
171 // Iterate over argument types
172 for (var aa = 0; aa < MAX_ARG_COUNT; ++aa) {
174 var argCompCount = argCompCounts[aa];
175 if (argCompCount !== undefined) {
176 var argVecType = vecBaseType + argCompCount;
177 var argType = (argCompCount === 1) ? scalarType : argVecType;
179 // Name of argument type with separating comma (if not last argument)
180 arg = argType + ((aa === argCompCounts.length - 1) ? "" : ", ");
183 subst["type" + aa] = arg;
186 return wtu.replaceParams(
187 "$(vecType)($(type0)$(type1)$(type2)$(type3)$(type4))",
193 // Returns if vector construction expression is valid or invalid
194 // The reason why the expression is invalid is encoded in the enumeration
195 function getVectorConstructorValidityType(argCompCounts, compCount) {
196 var totalCompCount = 0;
197 for (var aa = 0; aa < argCompCounts.length; ++aa)
198 totalCompCount += argCompCounts[aa];
200 if (totalCompCount === 0) {
201 // A constructor needs at least one value
202 return EXP_INVALID_NO_ARGS;
204 else if (totalCompCount === 1) {
205 // Constructors with one value set all components to the same value
208 else if (totalCompCount < compCount) {
209 // More than one value but not enough to set all components
210 return EXP_INVALID_NOT_ENOUGH_COMPS;
213 // totalCompCount >= compCount
214 // All components set
215 var lastArgFirstCompIx = totalCompCount - argCompCounts[argCompCounts.length - 1];
217 if (lastArgFirstCompIx < compCount) {
218 // All components set, all arguments used
222 // All components set, not all arguments used
223 return EXP_INVALID_TOO_MANY_ARGS;
229 // Return message for test (will be displayed)
230 function getTestMessage(compCount, vecBaseType, scalarType, argCompCounts, expValidity) {
232 switch (expValidity) {
234 msg = "Valid constructor expression";
235 if (argCompCounts.length === 1 && argCompCounts[0] === 1)
236 msg += " (all components set to the same value)";
240 case EXP_INVALID_NO_ARGS:
241 msg = "Invalid constructor expression (no arguments)";
244 case EXP_INVALID_NOT_ENOUGH_COMPS:
245 msg = "Invalid constructor expression (not enough arguments)";
248 case EXP_INVALID_TOO_MANY_ARGS:
249 msg = "Invalid constructor expression (unused argument)";
253 msg = "Unknown validity constant";
257 return msg + " : " + getConstructorTypeExpression(vecBaseType, compCount, scalarType, argCompCounts);
261 // Returns a testcase
262 function getVectorTestCase(compCount, vecBaseType, scalarType, argCompCounts, expValidity) {
263 var substitutions = getSubstitutions(vecBaseType, compCount, scalarType, argCompCounts);
264 var valid_exp = (expValidity === EXP_VALID);
268 // Test constructor argument list in fragment shader
269 vShaderSource: wtu.replaceParams(vectorConstructorVertexTemplate, substitutions),
270 vShaderSuccess: valid_exp,
271 fShaderSource: wtu.replaceParams(vectorConstructorFragmentTemplate, substitutions),
272 fShaderSuccess: valid_exp,
273 linkSuccess: valid_exp,
274 passMsg: getTestMessage(compCount, vecBaseType, scalarType, argCompCounts, expValidity),
281 // Increment the argument component counts
282 function incArgumentCounts(argCompCounts, compCount) {
283 // Valid test expressions are constructor expressions with maximum 1 not used argument with a component count of 1
285 // wtu.log("incArgumentCounts() enter : " + argCompCounts + ", comp count : " + compCount);
287 // Determine if there is an argument which will turn into a not used argument if the component count of the leading
288 // arguments is increased by one.
289 // The sum of argument components up till the current argument gives the component index of the first component
290 // of the current argument into the target type.
291 // Example : target vec3, arguments vec2, vec2
292 // Target t[0] t[1] t[2]
293 // Arguments a0[0] a0[1] a1[0] a1[1]
294 // a1[0] is at index 2 of the target type, this is the sum of components of the arguments before a1
296 var oneCompUsedIx = -1;
298 for (var aa = 0; aa < argCompCounts.length; ++aa) {
299 if (compSum === compCount - 1)
301 else if (compSum > compCount - 1)
304 compSum += argCompCounts[aa];
307 // If there is an argument with only one component used it is not allowed to turn into a not used argument if it has more than one
308 // component or it is not the last argument (there is already a not used argument).
310 if (oneCompUsedIx != -1 && (argCompCounts[oneCompUsedIx] > 1 || oneCompUsedIx < argCompCounts.length - 1))
311 noExpandIx = oneCompUsedIx;
313 // wtu.log("incArgumentCounts() no exp : " + noExpandIx);
315 // Find argument to increase
317 var compSumDelta = 0;
318 while (aa < argCompCounts.length && (argCompCounts[aa] === MAX_COMP_COUNT || (aa < noExpandIx && compSumDelta + 1 > 0))) {
319 // Current argument component count has maximum value or increasing the component count will generate an invalid test case
321 // Accumulate change in component count if component count for current argument is reset
322 compSumDelta += (-argCompCounts[aa] + 1);
324 // Reset to start with one component
325 argCompCounts[aa] = 1;
327 // Move to next argument
331 if (aa === argCompCounts.length) {
332 // Extend argument list with argument of one component (scalar)
333 argCompCounts.push(1);
336 if (aa * 1 > compCount - 1) {
337 // Not used argument, increasing the argument count of the not used argument
338 // End of test cases reached
339 argCompCounts.length = 0;
346 // wtu.log("incArgumentCounts() exit : " + argCompCounts);
352 // Returns the count of testcases for a datatype with a specified component count
353 function getTestCaseCount(compCount) {
354 if (compCount === 1) {
355 // Test case count for a data type with only one component
357 // The sequence of arguments with component count in the range { 1, ..., MAX_COMP_COUNT }
358 // multiplied with the count of tests of not used arguments plus one for no unused argument.
359 return 1 + MAX_COMP_COUNT * (1 + UNUSED_EXP_COUNT);
362 // One for the no arguments case
364 for (var cc = 1; cc <= MAX_COMP_COUNT; ++cc) {
365 if (cc < compCount) {
366 // For all arguments which are shorter compared to the target datatype
367 // Add the count of testcases for a data type with length one less
368 sum += getTestCaseCount(compCount - cc);
371 // For all arguments which have a length equal or greater compared to the
372 // component count of the target type :
373 // Add the count of unused argument test cases plus one for no unused argument.
374 sum += (1 + UNUSED_EXP_COUNT);
384 * Returns list of test cases for vector types
385 * All combinations of arguments up to one unused argument of one component are tested
386 * @param {prefixCompTypeName} Name of prefix (scalar) component type
387 * @param {compCount} Count of components in vector type
388 * @param {scalarType} Name of (scalar) component type
390 function getVectorConstructorTests(prefixCompTypeName, compCount, scalarType) {
391 // List of tests to return
394 // Complete name of vector type
395 var vecBaseType = prefixCompTypeName + "vec";
396 var vecType = vecBaseType + compCount;
398 // List of component count per argument
399 var argCompCounts = [];
400 var testCaseCount = 0;
403 var expValidity = getVectorConstructorValidityType(argCompCounts, compCount);
405 testInfos = testInfos.concat(getVectorTestCase(compCount, vecBaseType, scalarType, argCompCounts, expValidity));
408 // Move to next argument expression
409 incArgumentCounts(argCompCounts, compCount);
411 while (argCompCounts.length !== 0);
413 // Verify the pattern of generated testcases by comparing the count of
414 // testcases against a direct computation of the test case count
415 if (testCaseCount !== getTestCaseCount(compCount)) {
416 wtu.error("GLSLConstructorTestsGenerator.getVectorConstructorTests(), mismatch in count of testcases generated and computed testcase count");
426 getVectorConstructorTests: getVectorConstructorTests