Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / functional / gles3 / es3fUniformApiTests.js
blob59e50f1fc995a39a3e27dc2b81934f436b052014
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
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  */
21 'use strict';
22 goog.provide('functional.gles3.es3fUniformApiTests');
23 goog.require('framework.common.tcuSurface');
24 goog.require('framework.common.tcuTestCase');
25 goog.require('framework.common.tcuTexture');
26 goog.require('framework.delibs.debase.deMath');
27 goog.require('framework.delibs.debase.deRandom');
28 goog.require('framework.delibs.debase.deString');
29 goog.require('framework.opengl.gluDrawUtil');
30 goog.require('framework.opengl.gluShaderProgram');
31 goog.require('framework.opengl.gluShaderUtil');
32 goog.require('framework.opengl.gluTexture');
33 goog.require('framework.opengl.gluVarType');
35 goog.scope(function() {
37     var es3fUniformApiTests = functional.gles3.es3fUniformApiTests;
38     var gluDrawUtil = framework.opengl.gluDrawUtil;
39     var gluShaderUtil = framework.opengl.gluShaderUtil;
40     var gluShaderProgram = framework.opengl.gluShaderProgram;
41     var gluTexture = framework.opengl.gluTexture;
42     var gluVarType = framework.opengl.gluVarType;
43     var tcuTestCase = framework.common.tcuTestCase;
44     var tcuSurface = framework.common.tcuSurface;
45     var tcuTexture = framework.common.tcuTexture;
46     var deMath = framework.delibs.debase.deMath;
47     var deString = framework.delibs.debase.deString;
48     var deRandom = framework.delibs.debase.deRandom;
50     /** @type {WebGL2RenderingContext} */ var gl;
52     /** @typedef {function(gluShaderUtil.DataType): boolean} */
53     es3fUniformApiTests.dataTypePredicate;
55     /** @type {number} */ es3fUniformApiTests.MAX_RENDER_WIDTH = 32;
56     /** @type {number} */ es3fUniformApiTests.MAX_RENDER_HEIGHT = 32;
57     /** @type {number} */ es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS = 16;
59     /** @type {Array<gluShaderUtil.DataType>} */ es3fUniformApiTests.s_testDataTypes = [
60     gluShaderUtil.DataType.FLOAT,
61     gluShaderUtil.DataType.FLOAT_VEC2,
62     gluShaderUtil.DataType.FLOAT_VEC3,
63     gluShaderUtil.DataType.FLOAT_VEC4,
64     gluShaderUtil.DataType.FLOAT_MAT2,
65     gluShaderUtil.DataType.FLOAT_MAT2X3,
66     gluShaderUtil.DataType.FLOAT_MAT2X4,
67     gluShaderUtil.DataType.FLOAT_MAT3X2,
68     gluShaderUtil.DataType.FLOAT_MAT3,
69     gluShaderUtil.DataType.FLOAT_MAT3X4,
70     gluShaderUtil.DataType.FLOAT_MAT4X2,
71     gluShaderUtil.DataType.FLOAT_MAT4X3,
72     gluShaderUtil.DataType.FLOAT_MAT4,
74     gluShaderUtil.DataType.INT,
75     gluShaderUtil.DataType.INT_VEC2,
76     gluShaderUtil.DataType.INT_VEC3,
77     gluShaderUtil.DataType.INT_VEC4,
79     gluShaderUtil.DataType.UINT,
80     gluShaderUtil.DataType.UINT_VEC2,
81     gluShaderUtil.DataType.UINT_VEC3,
82     gluShaderUtil.DataType.UINT_VEC4,
84     gluShaderUtil.DataType.BOOL,
85     gluShaderUtil.DataType.BOOL_VEC2,
86     gluShaderUtil.DataType.BOOL_VEC3,
87     gluShaderUtil.DataType.BOOL_VEC4,
89     gluShaderUtil.DataType.SAMPLER_2D,
90     gluShaderUtil.DataType.SAMPLER_CUBE
91         // \note We don't test all sampler types here.
92     ];
94     /**
95      * Returns a substring from the beginning to the last occurence of the
96      * specified character
97      * @param {string} str The string in which to search
98      * @param {string} c A single character
99      * @return {string}
100      */
101     es3fUniformApiTests.beforeLast = function(str, c) {
102         return str.substring(0, str.lastIndexOf(c));
103     };
105     /**
106      * es3fUniformApiTests.fillWithColor
107      * @param {tcuTexture.PixelBufferAccess} access ,
108      * @param {Array<number>} color Array of four color components.
109      */
110     es3fUniformApiTests.fillWithColor = function(access, color) {
111         for (var z = 0; z < access.getDepth(); z++)
112         for (var y = 0; y < access.getHeight(); y++)
113         for (var x = 0; x < access.getWidth(); x++)
114             access.setPixel(color, x, y, z);
115     };
117     /**
118      * @param {gluShaderUtil.DataType} type
119      * @return {number}
120      */
121     es3fUniformApiTests.getSamplerNumLookupDimensions = function(type) {
122         switch (type) {
123             case gluShaderUtil.DataType.SAMPLER_2D:
124             case gluShaderUtil.DataType.INT_SAMPLER_2D:
125             case gluShaderUtil.DataType.UINT_SAMPLER_2D:
126                 return 2;
128             case gluShaderUtil.DataType.SAMPLER_3D:
129             case gluShaderUtil.DataType.INT_SAMPLER_3D:
130             case gluShaderUtil.DataType.UINT_SAMPLER_3D:
131             case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
132             case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
133             case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
134             case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
135             case gluShaderUtil.DataType.SAMPLER_CUBE:
136             case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
137             case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
138                 return 3;
140             case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
141             case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
142                 return 4;
144             default:
145                 throw new Error('es3fUniformApiTests.getSamplerNumLookupDimensions - Invalid type');
146         }
147     };
149    /**
150     * @param {gluShaderUtil.DataType} type
151     * @return {gluShaderUtil.DataType}
152     */
153     es3fUniformApiTests.getSamplerLookupReturnType = function(type) {
154         switch (type) {
155             case gluShaderUtil.DataType.SAMPLER_2D:
156             case gluShaderUtil.DataType.SAMPLER_CUBE:
157             case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
158             case gluShaderUtil.DataType.SAMPLER_3D:
159                 return gluShaderUtil.DataType.FLOAT_VEC4;
161             case gluShaderUtil.DataType.UINT_SAMPLER_2D:
162             case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
163             case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
164             case gluShaderUtil.DataType.UINT_SAMPLER_3D:
165                 return gluShaderUtil.DataType.UINT_VEC4;
167             case gluShaderUtil.DataType.INT_SAMPLER_2D:
168             case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
169             case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
170             case gluShaderUtil.DataType.INT_SAMPLER_3D:
171                 return gluShaderUtil.DataType.INT_VEC4;
173             case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
174             case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
175             case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
176                 return gluShaderUtil.DataType.FLOAT;
178             default:
179                 throw new Error('es3fUniformApiTests.getSamplerLookupReturnType - Invalid type');
180         }
181     };
183     /**
184      * @param {gluShaderUtil.DataType} T DataType to compare the type. Used to be a template param
185      * @param {gluShaderUtil.DataType} t
186      * @return {boolean}
187      */
188     es3fUniformApiTests.dataTypeEquals = function(T, t) {
189         return t == T;
190     };
192     /**
193      * @param {number} N Row number. Used to be a template parameter
194      * @param {gluShaderUtil.DataType} t
195      * @return {boolean}
196      */
197     es3fUniformApiTests.dataTypeIsMatrixWithNRows = function(N, t) {
198         return gluShaderUtil.isDataTypeMatrix(t) && gluShaderUtil.getDataTypeMatrixNumRows(t) == N;
199     };
201    /**
202     * @param {gluVarType.VarType} type
203     * @param {es3fUniformApiTests.dataTypePredicate} predicate
204     * @return {boolean}
205     */
206     es3fUniformApiTests.typeContainsMatchingBasicType = function(type, predicate) {
207         if (type.isBasicType())
208             return predicate(type.getBasicType());
209         else if (type.isArrayType())
210             return es3fUniformApiTests.typeContainsMatchingBasicType(type.getElementType(), predicate);
211         else {
212             assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.typeContainsMatchingBasicType - not a struct type', false, true);
213             /** @type {gluVarType.StructType} */ var structType = type.getStruct();
214             for (var i = 0; i < structType.getSize(); i++)
215                 if (es3fUniformApiTests.typeContainsMatchingBasicType(structType.getMember(i).getType(), predicate))
216                     return true;
217             return false;
218         }
219     };
221     /**
222      * @param {Array<gluShaderUtil.DataType>} dst
223      * @param {gluVarType.VarType} type
224      */
225     es3fUniformApiTests.getDistinctSamplerTypes = function(dst, type) {
226         if (type.isBasicType()) {
227             /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType();
228             if (gluShaderUtil.isDataTypeSampler(basicType) && dst.indexOf(basicType) == -1)
229                 dst.push(basicType);
230         } else if (type.isArrayType())
231             es3fUniformApiTests.getDistinctSamplerTypes(dst, type.getElementType());
232         else {
233             assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.getDistinctSamplerTypes - not a struct type', false, true);
234             /** @type {gluVarType.StructType} */ var structType = type.getStruct();
235             for (var i = 0; i < structType.getSize(); i++)
236                 es3fUniformApiTests.getDistinctSamplerTypes(dst, structType.getMember(i).getType());
237         }
238     };
240     /**
241      * @param {gluVarType.VarType} type
242      * @return {number}
243      */
244     es3fUniformApiTests.getNumSamplersInType = function(type) {
245         if (type.isBasicType())
246             return gluShaderUtil.isDataTypeSampler(type.getBasicType()) ? 1 : 0;
247         else if (type.isArrayType())
248             return es3fUniformApiTests.getNumSamplersInType(type.getElementType()) * type.getArraySize();
249         else {
250             assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.getNumSamplersInType - not a struct type', false, true);
251             /** @type {gluVarType.StructType} */ var structType = type.getStruct();
252             /** @type {number} */ var sum = 0;
253             for (var i = 0; i < structType.getSize(); i++)
254                 sum += es3fUniformApiTests.getNumSamplersInType(structType.getMember(i).getType());
255             return sum;
256         }
257     };
259     /** @typedef { {type: gluVarType.VarType, ndx: number}} */
260     es3fUniformApiTests.VarTypeWithIndex;
262     /**
263      * @param {number} maxDepth
264      * @param {number} curStructIdx Out parameter, instead returning it in the VarTypeWithIndex structure.
265      * @param {Array<gluVarType.StructType>} structTypesDst
266      * @param {deRandom.Random} rnd
267      * @return {es3fUniformApiTests.VarTypeWithIndex}
268      */
269     es3fUniformApiTests.generateRandomType = function(maxDepth, curStructIdx, structTypesDst, rnd) {
270         /** @type {boolean} */ var isStruct = maxDepth > 0 && rnd.getFloat() < 0.2;
271         /** @type {boolean} */ var isArray = rnd.getFloat() < 0.3;
273         if (isStruct) {
274             /** @type {number} */ var numMembers = rnd.getInt(1, 5);
275             /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + curStructIdx++);
277             for (var i = 0; i < numMembers; i++) {
278                 /** @type {es3fUniformApiTests.VarTypeWithIndex} */ var typeWithIndex = es3fUniformApiTests.generateRandomType(maxDepth - 1, curStructIdx, structTypesDst, rnd);
279                 curStructIdx = typeWithIndex.ndx;
280                 structType.addMember('m' + i, typeWithIndex.type);
281             }
283             structTypesDst.push(structType);
284             return (isArray ? {
285                 type: gluVarType.newTypeArray(gluVarType.newTypeStruct(structType), rnd.getInt(1, 5)),
286                 ndx: curStructIdx
287             }
288             : {
289                 type: gluVarType.newTypeStruct(structType),
290                 ndx: curStructIdx
291             });
292         } else {
293             /** @type {gluShaderUtil.DataType} */ var basicType = es3fUniformApiTests.s_testDataTypes[rnd.getInt(0, es3fUniformApiTests.s_testDataTypes.length - 1)];
294             /** @type {gluShaderUtil.precision} */ var precision;
295             if (!gluShaderUtil.isDataTypeBoolOrBVec(basicType))
296                 precision = gluShaderUtil.precision.PRECISION_MEDIUMP;
297             return (isArray ? {
298                 type: gluVarType.newTypeArray(gluVarType.newTypeBasic(basicType, precision), rnd.getInt(1, 5)),
299                 ndx: curStructIdx
300             }
301             : {
302                 type: gluVarType.newTypeBasic(basicType, precision),
303                 ndx: curStructIdx
304             });
305         }
306     };
308     /**
309      * es3fUniformApiTests.SamplerV structure
310      * @constructor
311      */
312     es3fUniformApiTests.SamplerV = function() {
313         this.samplerV = {
314             /** @type {number} */ unit: 0,
315             /** @type {Array<number>} */ fillColor: []
316         };
317     };
319     /**
320      * es3fUniformApiTests.VarValue class. may contain different types.
321      * @constructor
322      */
323     es3fUniformApiTests.VarValue = function() {
324         /** @type {gluShaderUtil.DataType} */ this.type;
325         /** @type {Array<number | boolean> | es3fUniformApiTests.SamplerV} */ this.val = [];
326     };
328     /**
329      * @enum {number}
330      */
331     es3fUniformApiTests.CaseShaderType = {
332         VERTEX: 0,
333         FRAGMENT: 1,
334         BOTH: 2
335     };
337     /**
338      * es3fUniformApiTests.Uniform struct.
339      * @param {string} name_
340      * @param {gluVarType.VarType} type_
341      * @constructor
342      */
343     es3fUniformApiTests.Uniform = function(name_, type_) {
344         /** @type {string} */ this.name = name_;
345         /** @type {gluVarType.VarType} */ this.type = type_;
346     };
348     // A set of uniforms, along with related struct types.
349     /**
350      * class es3fUniformApiTests.UniformCollection
351      * @constructor
352      */
353     es3fUniformApiTests.UniformCollection = function() {
354         /** @type {Array<es3fUniformApiTests.Uniform>} */ this.m_uniforms = [];
355         /** @type {Array<gluVarType.StructType>} */ this.m_structTypes = [];
356     };
358     /**
359      * @return {number}
360      */
361     es3fUniformApiTests.UniformCollection.prototype.getNumUniforms = function() {return this.m_uniforms.length;};
363     /**
364      * @return {number}
365      */
366     es3fUniformApiTests.UniformCollection.prototype.getNumStructTypes = function() {return this.m_structTypes.length;};
368     /**
369      * @param {number} ndx
370      * @return {es3fUniformApiTests.Uniform}
371      */
372     es3fUniformApiTests.UniformCollection.prototype.getUniform = function(ndx) {return this.m_uniforms[ndx];};
374     /**
375      * @param {number} ndx
376      * @return {gluVarType.StructType}
377      */
378     es3fUniformApiTests.UniformCollection.prototype.getStructType = function(ndx) {return this.m_structTypes[ndx];};
380     /**
381      * @param {es3fUniformApiTests.Uniform} uniform
382      */
383     es3fUniformApiTests.UniformCollection.prototype.addUniform = function(uniform) {this.m_uniforms.push(uniform);};
385     /**
386      * @param {gluVarType.StructType} type
387      */
388     es3fUniformApiTests.UniformCollection.prototype.addStructType = function(type) {this.m_structTypes.push(type);};
390     // Add the contents of m_uniforms and m_structTypes to receiver, and remove them from this one.
391     // \note receiver takes ownership of the struct types.
392     /**
393      * @param {es3fUniformApiTests.UniformCollection} receiver
394      */
395     es3fUniformApiTests.UniformCollection.prototype.moveContents = function(receiver) {
396         for (var i = 0; i < this.m_uniforms.length; i++)
397             receiver.addUniform(this.m_uniforms[i]);
398         this.m_uniforms.length = 0;
400         for (var i = 0; i < this.m_structTypes.length; i++)
401             receiver.addStructType(this.m_structTypes[i]);
402         this.m_structTypes.length = 0;
403     };
405     /**
406      * @param {es3fUniformApiTests.dataTypePredicate} predicate
407      * @return {boolean}
408      */
409     es3fUniformApiTests.UniformCollection.prototype.containsMatchingBasicType = function(predicate) {
410         for (var i = 0; i < this.m_uniforms.length; i++)
411             if (es3fUniformApiTests.typeContainsMatchingBasicType(this.m_uniforms[i].type, predicate))
412                 return true;
413         return false;
414     };
416     /**
417      * @return {Array<gluShaderUtil.DataType>}
418      */
419     es3fUniformApiTests.UniformCollection.prototype.getSamplerTypes = function() {
420         /** @type {Array<gluShaderUtil.DataType>} */ var samplerTypes = [];
421         for (var i = 0; i < this.m_uniforms.length; i++)
422             es3fUniformApiTests.getDistinctSamplerTypes(samplerTypes, this.m_uniforms[i].type);
423         return samplerTypes;
424     };
426     /**
427      * @return {boolean}
428      */
429     es3fUniformApiTests.UniformCollection.prototype.containsSeveralSamplerTypes = function() {
430         return this.getSamplerTypes().length > 1;
431     };
433     /**
434      * @return {number}
435      */
436     es3fUniformApiTests.UniformCollection.prototype.getNumSamplers = function() {
437         var sum = 0;
438         for (var i = 0; i < this.m_uniforms.length; i++)
439             sum += es3fUniformApiTests.getNumSamplersInType(this.m_uniforms[i].type);
440         return sum;
441     };
443     /**
444      * @param {gluShaderUtil.DataType} type
445      * @param {string=} nameSuffix
446      * @return {es3fUniformApiTests.UniformCollection}
447      */
448     es3fUniformApiTests.UniformCollection.basic = function(type, nameSuffix) {
449         if (nameSuffix === undefined) nameSuffix = '';
450         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
451         /** @type {gluShaderUtil.precision} */ var prec;
452         if (!gluShaderUtil.isDataTypeBoolOrBVec(type))
453             prec = gluShaderUtil.precision.PRECISION_MEDIUMP;
454         res.m_uniforms.push(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeBasic(type, prec)));
455         return res;
456     };
458     /**
459      * @param {gluShaderUtil.DataType} type
460      * @param {string=} nameSuffix
461      * @return {es3fUniformApiTests.UniformCollection}
462      */
463     es3fUniformApiTests.UniformCollection.basicArray = function(type, nameSuffix) {
464         if (nameSuffix === undefined) nameSuffix = '';
465         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
466         /** @type {gluShaderUtil.precision} */ var prec;
467         if (!gluShaderUtil.isDataTypeBoolOrBVec(type))
468             prec = gluShaderUtil.precision.PRECISION_MEDIUMP;
469         res.m_uniforms.push(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeArray(gluVarType.newTypeBasic(type, prec), 3)));
470         return res;
471     };
473     /**
474      * @param {gluShaderUtil.DataType} type0
475      * @param {gluShaderUtil.DataType} type1
476      * @param {boolean} containsArrays
477      * @param {string=} nameSuffix
478      * @return {es3fUniformApiTests.UniformCollection}
479      */
480     es3fUniformApiTests.UniformCollection.basicStruct = function(type0, type1, containsArrays, nameSuffix) {
481         if (nameSuffix === undefined) nameSuffix = '';
482         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
483         /** @type {gluShaderUtil.precision} */ var prec0;
484         if (!gluShaderUtil.isDataTypeBoolOrBVec(type0))
485             prec0 = gluShaderUtil.precision.PRECISION_MEDIUMP;
486         /** @type {gluShaderUtil.precision} */ var prec1;
487         if (!gluShaderUtil.isDataTypeBoolOrBVec(type1))
488             prec1 = gluShaderUtil.precision.PRECISION_MEDIUMP;
490         /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + nameSuffix);
491         structType.addMember('m0', gluVarType.newTypeBasic(type0, prec0));
492         structType.addMember('m1', gluVarType.newTypeBasic(type1, prec1));
493         if (containsArrays) {
494             structType.addMember('m2', gluVarType.newTypeArray(gluVarType.newTypeBasic(type0, prec0), 3));
495             structType.addMember('m3', gluVarType.newTypeArray(gluVarType.newTypeBasic(type1, prec1), 3));
496         }
498         res.addStructType(structType);
499         res.addUniform(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeStruct(structType)));
501         return res;
502     };
504     /**
505      * @param {gluShaderUtil.DataType} type0
506      * @param {gluShaderUtil.DataType} type1
507      * @param {boolean} containsArrays
508      * @param {string=} nameSuffix
509      * @return {es3fUniformApiTests.UniformCollection}
510      */
511     es3fUniformApiTests.UniformCollection.structInArray = function(type0, type1, containsArrays, nameSuffix) {
512         if (nameSuffix === undefined) nameSuffix = '';
513         /** @type {es3fUniformApiTests.UniformCollection} */ var res = es3fUniformApiTests.UniformCollection.basicStruct(type0, type1, containsArrays, nameSuffix);
514         res.getUniform(0).type = gluVarType.newTypeArray(res.getUniform(0).type, 3);
515         return res;
516     };
518     /**
519      * @param {gluShaderUtil.DataType} type0
520      * @param {gluShaderUtil.DataType} type1
521      * @param {string=} nameSuffix
522      * @return {es3fUniformApiTests.UniformCollection}
523      */
524     es3fUniformApiTests.UniformCollection.nestedArraysStructs = function(type0, type1, nameSuffix) {
525         if (nameSuffix === undefined) nameSuffix = '';
526         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
527         /** @type {gluShaderUtil.precision} */ var prec0;
528         if (!gluShaderUtil.isDataTypeBoolOrBVec(type0))
529             prec0 = gluShaderUtil.precision.PRECISION_MEDIUMP;
530         /** @type {gluShaderUtil.precision} */ var prec1;
531         if (!gluShaderUtil.isDataTypeBoolOrBVec(type1))
532             prec1 = gluShaderUtil.precision.PRECISION_MEDIUMP;
533         /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + nameSuffix);
534         /** @type {gluVarType.StructType} */ var subStructType = gluVarType.newStructType('subStructType' + nameSuffix);
535         /** @type {gluVarType.StructType} */ var subSubStructType = gluVarType.newStructType('subSubStructType' + nameSuffix);
537         subSubStructType.addMember('mss0', gluVarType.newTypeBasic(type0, prec0));
538         subSubStructType.addMember('mss1', gluVarType.newTypeBasic(type1, prec1));
540         subStructType.addMember('ms0', gluVarType.newTypeBasic(type1, prec1));
541         subStructType.addMember('ms1', gluVarType.newTypeArray(gluVarType.newTypeBasic(type0, prec0), 2));
542         subStructType.addMember('ms2', gluVarType.newTypeArray(gluVarType.newTypeStruct(subSubStructType), 2));
544         structType.addMember('m0', gluVarType.newTypeBasic(type0, prec0));
545         structType.addMember('m1', gluVarType.newTypeStruct(subStructType));
546         structType.addMember('m2', gluVarType.newTypeBasic(type1, prec1));
548         res.addStructType(subSubStructType);
549         res.addStructType(subStructType);
550         res.addStructType(structType);
552         res.addUniform(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeStruct(structType)));
554         return res;
555     };
557     /**
558      * @param {string=} nameSuffix
559      * @return {es3fUniformApiTests.UniformCollection}
560      */
561     es3fUniformApiTests.UniformCollection.multipleBasic = function(nameSuffix) {
562         if (nameSuffix === undefined) nameSuffix = '';
563         /** @type {Array<gluShaderUtil.DataType>} */ var types = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT_VEC3, gluShaderUtil.DataType.UINT_VEC4, gluShaderUtil.DataType.FLOAT_MAT3, gluShaderUtil.DataType.BOOL_VEC2];
564         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
566         for (var i = 0; i < types.length; i++) {
567             /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.basic(types[i], '_' + i + nameSuffix);
568             sub.moveContents(res);
569         }
571         return res;
572     };
574     /**
575      * @param {string=} nameSuffix
576      * @return {es3fUniformApiTests.UniformCollection}
577      */
578     es3fUniformApiTests.UniformCollection.multipleBasicArray = function(nameSuffix) {
579         if (nameSuffix === undefined) nameSuffix = '';
580         /** @type {Array<gluShaderUtil.DataType>} */ var types = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT_VEC3, gluShaderUtil.DataType.BOOL_VEC2];
581         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
583         for (var i = 0; i < types.length; i++) {
584             /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.basicArray(types[i], '_' + i + nameSuffix);
585             sub.moveContents(res);
586         }
588         return res;
589     };
591     /**
592      * @param {string=} nameSuffix
593      * @return {es3fUniformApiTests.UniformCollection}
594      */
595     es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs = function(nameSuffix) {
596         if (nameSuffix === undefined) nameSuffix = '';
597         /** @type {Array<gluShaderUtil.DataType>} */ var types0 = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT, gluShaderUtil.DataType.BOOL_VEC4];
598         /** @type {Array<gluShaderUtil.DataType>} */ var types1 = [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.INT_VEC4, gluShaderUtil.DataType.BOOL];
599         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
601         assertMsgOptions(types0.length == types1.length, 'es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs - lengths are not the same', false, true);
603         for (var i = 0; i < types0.length; i++) {
604             /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.nestedArraysStructs(types0[i], types1[i], '_' + i + nameSuffix);
605             sub.moveContents(res);
606         }
608         return res;
609     };
611     /**
612      * @param {number} seed
613      * @return {es3fUniformApiTests.UniformCollection}
614      */
615     es3fUniformApiTests.UniformCollection.random = function(seed) {
616         /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
617         /** @type {number} */ var numUniforms = rnd.getInt(1, 5);
618         /** @type {number} */ var structIdx = 0;
619         /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
621         for (var i = 0; i < numUniforms; i++) {
622             /** @type {Array<gluVarType.StructType>} */ var structTypes = [];
623             /** @type {es3fUniformApiTests.Uniform} */ var uniform = new es3fUniformApiTests.Uniform('u_var' + i, new gluVarType.VarType());
625             // \note Discard uniforms that would cause number of samplers to exceed es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS.
626             do {
627                 var temp = es3fUniformApiTests.generateRandomType(3, structIdx, structTypes, rnd);
628                 structIdx = temp.ndx;
629                 uniform.type = temp.type;
630             } while (res.getNumSamplers() + es3fUniformApiTests.getNumSamplersInType(uniform.type) > es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS);
632             res.addUniform(uniform);
633             for (var j = 0; j < structTypes.length; j++)
634                 res.addStructType(structTypes[j]);
635         }
637         return res;
638     };
640     /**
641      * @param {es3fUniformApiTests.VarValue} sampler
642      * @return {es3fUniformApiTests.VarValue}
643      */
644     es3fUniformApiTests.getSamplerFillValue = function(sampler) {
645         assertMsgOptions(gluShaderUtil.isDataTypeSampler(sampler.type), 'es3fUniformApiTests.getSamplerFillValue - not a sampler type', false, true);
647         /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
648         result.type = es3fUniformApiTests.getSamplerLookupReturnType(sampler.type);
650         switch (result.type) {
651             case gluShaderUtil.DataType.FLOAT_VEC4:
652                 for (var i = 0; i < 4; i++)
653                     result.val[i] = sampler.val.samplerV.fillColor[i];
654                 break;
655             case gluShaderUtil.DataType.UINT_VEC4:
656                 for (var i = 0; i < 4; i++)
657                     result.val[i] = sampler.val.samplerV.fillColor[i];
658                 break;
659             case gluShaderUtil.DataType.INT_VEC4:
660                 for (var i = 0; i < 4; i++)
661                     result.val[i] = sampler.val.samplerV.fillColor[i];
662                 break;
663             case gluShaderUtil.DataType.FLOAT:
664                 result.val[0] = sampler.val.samplerV.fillColor[0];
665                 break;
666             default:
667                 throw new Error('es3fUniformApiTests.getSamplerFillValue - Invalid type');
668         }
670         return result;
671     };
673     /**
674      * @param {es3fUniformApiTests.VarValue} sampler
675      * @return {es3fUniformApiTests.VarValue}
676      */
677     es3fUniformApiTests.getSamplerUnitValue = function(sampler) {
678         assertMsgOptions(gluShaderUtil.isDataTypeSampler(sampler.type), 'es3fUniformApiTests.getSamplerUnitValue - not a sampler type', false, true);
680         /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
681         result.type = gluShaderUtil.DataType.INT;
682         result.val[0] = sampler.val.samplerV.unit;
684         return result;
685     };
687     /**
688      * @param {gluShaderUtil.DataType} original
689      * @return {gluShaderUtil.DataType}
690      */
691     es3fUniformApiTests.getDataTypeTransposedMatrix = function(original) {
692         return gluShaderUtil.getDataTypeMatrix(gluShaderUtil.getDataTypeMatrixNumRows(original), gluShaderUtil.getDataTypeMatrixNumColumns(original));
693     };
695     /**
696      * @param {es3fUniformApiTests.VarValue} original
697      * @return {es3fUniformApiTests.VarValue}
698      */
699     es3fUniformApiTests.getTransposeMatrix = function(original) {
700         assertMsgOptions(gluShaderUtil.isDataTypeMatrix(original.type), 'es3fUniformApiTests.getTransposeMatrix - not a matrix', false, true);
702         /** @type {number} */ var rows = gluShaderUtil.getDataTypeMatrixNumRows(original.type);
703         /** @type {number} */ var cols = gluShaderUtil.getDataTypeMatrixNumColumns(original.type);
704         /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
705         result.type = es3fUniformApiTests.getDataTypeTransposedMatrix(original.type);
707         for (var i = 0; i < rows; i++)
708         for (var j = 0; j < cols; j++)
709             result.val[i * cols + j] = original.val[j * rows + i];
711         return result;
712     };
714     /**
715      * @param {es3fUniformApiTests.VarValue} value
716      * @return {string}
717      */
718     es3fUniformApiTests.shaderVarValueStr = function(value) {
719         /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(value.type);
720         /** @type {string} */ var result = '';
722         if (numElems > 1)
723             result += gluShaderUtil.getDataTypeName(value.type) + '(';
725         for (var i = 0; i < numElems; i++) {
726             if (i > 0)
727                 result += ', ';
729             if (gluShaderUtil.isDataTypeFloatOrVec(value.type) || gluShaderUtil.isDataTypeMatrix(value.type))
730                 result += value.val[i].toFixed(2);
731             else if (gluShaderUtil.isDataTypeIntOrIVec((value.type)))
732                 result += value.val[i];
733             else if (gluShaderUtil.isDataTypeUintOrUVec((value.type)))
734                 result += value.val[i] + 'u';
735             else if (gluShaderUtil.isDataTypeBoolOrBVec((value.type)))
736                 result += value.val[i] ? 'true' : 'false';
737             else if (gluShaderUtil.isDataTypeSampler((value.type)))
738                 result += es3fUniformApiTests.shaderVarValueStr(es3fUniformApiTests.getSamplerFillValue(value));
739             else
740                 throw new Error('es3fUniformApiTests.shaderVarValueStr - invalid type');
741         }
743         if (numElems > 1)
744             result += ')';
746         return result;
747     };
749     /**
750      * @param {es3fUniformApiTests.VarValue} value
751      * @return {string}
752      */
753     es3fUniformApiTests.apiVarValueStr = function(value) {
754         /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(value.type);
755         /** @type {string} */ var result = '';
757         if (numElems > 1)
758             result += '(';
760         for (var i = 0; i < numElems; i++) {
761             if (i > 0)
762                 result += ', ';
764             if (gluShaderUtil.isDataTypeFloatOrVec(value.type) || gluShaderUtil.isDataTypeMatrix(value.type))
765                 result += value.val[i].toFixed(2);
766             else if (gluShaderUtil.isDataTypeIntOrIVec(value.type) ||
767             gluShaderUtil.isDataTypeUintOrUVec(value.type))
768                 result += value.val[i];
769             else if (gluShaderUtil.isDataTypeBoolOrBVec(value.type))
770                 result += value.val[i] ? 'true' : 'false';
771             else if (gluShaderUtil.isDataTypeSampler(value.type))
772                 result += value.val.samplerV.unit;
773             else
774                 throw new Error('es3fUniformApiTests.apiVarValueStr - Invalid type');
775         }
777         if (numElems > 1)
778             result += ')';
780         return result;
781     };
783     // samplerUnit used if type is a sampler type. \note Samplers' unit numbers are not randomized.
784     /**
785      * @param {gluShaderUtil.DataType} type
786      * @param {deRandom.Random} rnd
787      * @param {number=} samplerUnit
788      * @return {es3fUniformApiTests.VarValue}
789      */
790     es3fUniformApiTests.generateRandomVarValue = function(type, rnd, samplerUnit) {
791         if (samplerUnit === undefined) samplerUnit = -1;
792         /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(type);
793         /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
794         result.type = type;
796         assertMsgOptions(
797             (samplerUnit >= 0) == (gluShaderUtil.isDataTypeSampler(type)),
798             'es3fUniformApiTests.generateRandomVarValue - sampler units do not match type', false, true
799         );
801         if (gluShaderUtil.isDataTypeFloatOrVec(type) || gluShaderUtil.isDataTypeMatrix(type)) {
802             for (var i = 0; i < numElems; i++)
803                 result.val[i] = rnd.getFloat(-10.0, 10.0);
804         } else if (gluShaderUtil.isDataTypeIntOrIVec(type)) {
805             for (var i = 0; i < numElems; i++)
806                 result.val[i] = rnd.getInt(-10, 10);
807         } else if (gluShaderUtil.isDataTypeUintOrUVec(type)) {
808             for (var i = 0; i < numElems; i++)
809                 result.val[i] = rnd.getInt(0, 10);
810         } else if (gluShaderUtil.isDataTypeBoolOrBVec(type)) {
811             for (var i = 0; i < numElems; i++)
812                 result.val[i] = rnd.getBool();
813         } else if (gluShaderUtil.isDataTypeSampler(type)) {
814             /** @type {gluShaderUtil.DataType} */ var texResultType = es3fUniformApiTests.getSamplerLookupReturnType(type);
815             /** @type {gluShaderUtil.DataType} */ var texResultScalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(texResultType);
816             /** @type {number} */ var texResultNumDims = gluShaderUtil.getDataTypeScalarSize(texResultType);
818             result.val = new es3fUniformApiTests.SamplerV();
819             result.val.samplerV.unit = samplerUnit;
821             for (var i = 0; i < texResultNumDims; i++) {
822                 switch (texResultScalarType) {
823                     case gluShaderUtil.DataType.FLOAT: result.val.samplerV.fillColor[i] = rnd.getFloat(0.0, 1.0); break;
824                     case gluShaderUtil.DataType.INT: result.val.samplerV.fillColor[i] = rnd.getInt(-10, 10); break;
825                     case gluShaderUtil.DataType.UINT: result.val.samplerV.fillColor[i] = rnd.getInt(0, 10); break;
826                     default:
827                         throw new Error('es3fUniformApiTests.generateRandomVarValue - Invalid scalar type');
828                 }
829             }
830         } else
831             throw new Error('es3fUniformApiTests.generateRandomVarValue - Invalid type');
833         return result;
834     };
836     /**
837      * @param {gluShaderUtil.DataType} type
838      * @return {es3fUniformApiTests.VarValue}
839      */
840     es3fUniformApiTests.generateZeroVarValue = function(type) {
841         /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(type);
842         /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
843         result.type = type;
845         if (gluShaderUtil.isDataTypeFloatOrVec(type) || gluShaderUtil.isDataTypeMatrix(type)) {
846             for (var i = 0; i < numElems; i++)
847                 result.val[i] = 0.0;
848         } else if (gluShaderUtil.isDataTypeIntOrIVec(type)) {
849             for (var i = 0; i < numElems; i++)
850                 result.val[i] = 0;
851         } else if (gluShaderUtil.isDataTypeUintOrUVec(type)) {
852             for (var i = 0; i < numElems; i++)
853                 result.val[i] = 0;
854         } else if (gluShaderUtil.isDataTypeBoolOrBVec(type)) {
855             for (var i = 0; i < numElems; i++)
856                 result.val[i] = false;
857         } else if (gluShaderUtil.isDataTypeSampler(type)) {
858             /** @type {gluShaderUtil.DataType} */ var texResultType = es3fUniformApiTests.getSamplerLookupReturnType(type);
859             /** @type {gluShaderUtil.DataType} */ var texResultScalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(texResultType);
860             /** @type {number} */ var texResultNumDims = gluShaderUtil.getDataTypeScalarSize(texResultType);
862             result.val = new es3fUniformApiTests.SamplerV();
863             result.val.samplerV.unit = 0;
865             for (var i = 0; i < texResultNumDims; i++) {
866                 switch (texResultScalarType) {
867                     case gluShaderUtil.DataType.FLOAT: result.val.samplerV.fillColor[i] = 0.12 * i; break;
868                     case gluShaderUtil.DataType.INT: result.val.samplerV.fillColor[i] = -2 + i; break;
869                     case gluShaderUtil.DataType.UINT: result.val.samplerV.fillColor[i] = 4 + i; break;
870                     default:
871                         throw new Error('es3fUniformApiTests.generateZeroVarValue - Invalid scalar type');
872                 }
873             }
874         } else
875             throw new Error('es3fUniformApiTests.generateZeroVarValue - Invalid type');
877         return result;
878     };
880     /**
881      * @param {es3fUniformApiTests.VarValue} a
882      * @param {es3fUniformApiTests.VarValue} b
883      * @return {boolean}
884      */
885     es3fUniformApiTests.apiVarValueEquals = function(a, b) {
886         /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(a.type);
887         /** @type {number} */ var floatThreshold = 0.05;
889         assertMsgOptions(a.type == b.type, 'es3fUniformApiTests.apiVarValueEquals - types are different', false, true);
891         if (gluShaderUtil.isDataTypeFloatOrVec(a.type) || gluShaderUtil.isDataTypeMatrix(a.type)) {
892             for (var i = 0; i < size; i++)
893                 if (Math.abs(a.val[i] - b.val[i]) >= floatThreshold)
894                     return false;
895         } else if (gluShaderUtil.isDataTypeIntOrIVec(a.type)) {
896             for (var i = 0; i < size; i++)
897                 if (a.val[i] != b.val[i])
898                     return false;
899         } else if (gluShaderUtil.isDataTypeUintOrUVec(a.type)) {
900             for (var i = 0; i < size; i++)
901                 if (a.val[i] != b.val[i])
902                     return false;
903         } else if (gluShaderUtil.isDataTypeBoolOrBVec(a.type)) {
904             for (var i = 0; i < size; i++)
905                 if (a.val[i] != b.val[i])
906                     return false;
907         } else if (gluShaderUtil.isDataTypeSampler(a.type)) {
908             if (a.val.samplerV.unit != b.val.samplerV.unit)
909                 return false;
910         } else
911             throw new Error('es3fUniformApiTests.apiVarValueEquals - Invalid type');
913         return true;
914     };
916     /**
917      * @param {es3fUniformApiTests.VarValue} boolValue
918      * @param {gluShaderUtil.DataType} targetScalarType
919      * @param {deRandom.Random} rnd
920      * @return {es3fUniformApiTests.VarValue}
921      */
922     es3fUniformApiTests.getRandomBoolRepresentation = function(boolValue, targetScalarType, rnd) {
923         assertMsgOptions(
924             gluShaderUtil.isDataTypeBoolOrBVec(boolValue.type),
925             'es3fUniformApiTests.getRandomBoolRepresentation - Data type not boolean or boolean vector',
926             false,
927             true
928         );
930         /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(boolValue.type);
931         /** @type {gluShaderUtil.DataType} */ var targetType = size == 1 ? targetScalarType : gluShaderUtil.getDataTypeVector(targetScalarType, size);
932         /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
933         result.type = targetType;
935         switch (targetScalarType) {
936             case gluShaderUtil.DataType.INT:
937                 for (var i = 0; i < size; i++) {
938                     if (boolValue.val[i]) {
939                         result.val[i] = rnd.getInt(-10, 10);
940                         if (result.val[i] == 0)
941                             result.val[i] = 1;
942                     } else
943                         result.val[i] = 0;
944                 }
945                 break;
947             case gluShaderUtil.DataType.UINT:
948                 for (var i = 0; i < size; i++) {
949                     if (boolValue.val[i])
950                         result.val[i] = rnd.getInt(1, 10);
951                     else
952                         result.val[i] = 0;
953                 }
954                 break;
956             case gluShaderUtil.DataType.FLOAT:
957                 for (var i = 0; i < size; i++) {
958                     if (boolValue.val[i]) {
959                         result.val[i] = rnd.getFloat(-10.0, 10.0);
960                         if (result.val[i] == 0.0)
961                             result.val[i] = 1.0;
962                     } else
963                         result.val[i] = 0;
964                 }
965                 break;
967             default:
968                 throw new Error('es3fUniformApiTests.getRandomBoolRepresentation - Invalid type');
969         }
971         return result;
972     };
974     /**
975      * @param {es3fUniformApiTests.CaseShaderType} type
976      * @return {?string}
977      */
978     es3fUniformApiTests.getCaseShaderTypeName = function(type) {
979         switch (type) {
980             case es3fUniformApiTests.CaseShaderType.VERTEX: return 'vertex';
981             case es3fUniformApiTests.CaseShaderType.FRAGMENT: return 'fragment';
982             case es3fUniformApiTests.CaseShaderType.BOTH: return 'both';
983             default:
984                 throw new Error('es3fUniformApiTests.getCaseShaderTypeName - Invalid shader type');
985         }
986     };
988     /**
989      * @param {number} seed
990      * @return {number}
991      */
992     es3fUniformApiTests.randomCaseShaderType = function(seed) {
993         return (new deRandom.Random(seed)).getInt(0, Object.keys(es3fUniformApiTests.CaseShaderType).length - 1);
994     };
996     //es3fUniformApiTests.UniformCase definitions
998     /**
999      * es3fUniformApiTests.Feature - Implemented as a function to create an object without unwanted properties.
1000      * @constructor
1001      */
1002     es3fUniformApiTests.Feature = function() {
1003         // ARRAYUSAGE_ONLY_MIDDLE_INDEX: only middle index of each array is used in shader. If not given, use all indices.
1004         this.ARRAYUSAGE_ONLY_MIDDLE_INDEX = false;
1006         // UNIFORMFUNC_VALUE: use pass-by-value versions of uniform assignment funcs, e.g. glUniform1f(), where possible. If not given, use pass-by-pointer versions.
1007         this.UNIFORMFUNC_VALUE = false;
1009         // MATRIXMODE_ROWMAJOR: pass matrices to GL in row major form. If not given, use column major.
1010         this.MATRIXMODE_ROWMAJOR = false;
1012         // ARRAYASSIGN: how basic-type arrays are assigned with glUniform*(). If none given, assign each element of an array separately.
1013         this.ARRAYASSIGN_FULL = false; //!< Assign all elements of an array with one glUniform*().
1014         this.ARRAYASSIGN_BLOCKS_OF_TWO = false; //!< Assign two elements per one glUniform*().
1016         // UNIFORMUSAGE_EVERY_OTHER: use about half of the uniforms. If not given, use all uniforms (except that some array indices may be omitted according to ARRAYUSAGE).
1017         this.UNIFORMUSAGE_EVERY_OTHER = false;
1019         // BOOLEANAPITYPE: type used to pass booleans to and from GL api. If none given, use float.
1020         this.BOOLEANAPITYPE_INT = false;
1021         this.BOOLEANAPITYPE_UINT = false;
1023         // UNIFORMVALUE_ZERO: use zero-valued uniforms. If not given, use random uniform values.
1024         this.UNIFORMVALUE_ZERO = false;
1026         // ARRAY_FIRST_ELEM_NAME_NO_INDEX: in certain API functions, when referring to the first element of an array, use just the array name without [0] at the end.
1027         this.ARRAY_FIRST_ELEM_NAME_NO_INDEX = false;
1028     };
1030     // A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d).
1031     /**
1032      * @constructor
1033      * @param {string} name_
1034      * @param {gluShaderUtil.DataType} type_
1035      * @param {boolean} isUsedInShader_
1036      * @param {es3fUniformApiTests.VarValue} finalValue_
1037      * @param {string=} rootName_
1038      * @param {number=} elemNdx_
1039      * @param {number=} rootSize_
1040      */
1041     es3fUniformApiTests.BasicUniform = function(name_, type_, isUsedInShader_, finalValue_, rootName_, elemNdx_, rootSize_) {
1042         /** @type {string} */ this.name = name_;
1043         /** @type {gluShaderUtil.DataType} */ this.type = type_;
1044         /** @type {boolean} */ this.isUsedInShader = isUsedInShader_;
1045         /** @type {es3fUniformApiTests.VarValue} */ this.finalValue = finalValue_; //!< The value we ultimately want to set for this uniform.
1047         /** @type {string} */ this.rootName = rootName_ === undefined ? name_ : rootName_; //!< If this is a member of a basic-typed array, rootName is the name of that array with "[0]" appended. Otherwise it equals name.
1048         /** @type {number} */ this.elemNdx = elemNdx_ === undefined ? -1 : elemNdx_; //!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1.
1049         /** @type {number} */ this.rootSize = rootSize_ === undefined ? 1 : rootSize_; //!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1.
1050     };
1052     /**
1053      * @param {Array<es3fUniformApiTests.BasicUniform>} vec
1054      * @param {string} name
1055      * @return {es3fUniformApiTests.BasicUniform}
1056      */
1057     es3fUniformApiTests.BasicUniform.findWithName = function(vec, name) {
1058         for (var i = 0; i < vec.length; i++) {
1059             if (vec[i].name == name)
1060                 return vec[i];
1061         }
1062         return null;
1063     };
1065     // Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniforms().
1066     /**
1067      * @constructor
1068      * @param {string} name_
1069      * @param {gluShaderUtil.DataType} type_
1070      * @param {boolean} used
1071      */
1072     es3fUniformApiTests.BasicUniformReportRef = function(name_, type_, used) {
1073         /** @type {string} */ this.name = name_;
1074         // \note minSize and maxSize are for arrays and can be distinct since implementations are allowed, but not required, to trim the inactive end indices of arrays.
1075         /** @type {number} */ this.minSize = 1;
1076         /** @type {number} */ this.maxSize = 1;
1077         /** @type {gluShaderUtil.DataType} */ this.type = type_;
1078         /** @type {boolean} */ this.isUsedInShader = used;
1079     };
1081     /**
1082      * To be used after constructor
1083      * @param {number} minS
1084      * @param {number} maxS
1085      * @return {es3fUniformApiTests.BasicUniformReportRef}
1086      */
1087     es3fUniformApiTests.BasicUniformReportRef.prototype.constructor_A = function(minS, maxS) {
1088         this.minSize = minS;
1089         this.maxSize = maxS;
1091         assertMsgOptions(
1092             this.minSize <= this.maxSize,
1093             'es3fUniformApiTests.BasicUniformReportRef.prototype.constructor_A - min size not smaller or equal than max size',
1094             false,
1095             true
1096         );
1098         return this;
1099     };
1101     // Info that is actually reported by glGetActiveUniform() or glGetActiveUniforms().
1102     /**
1103      * @constructor
1104      * @param {string} name_
1105      * @param {number} nameLength_
1106      * @param {number} size_
1107      * @param {gluShaderUtil.DataType} type_
1108      * @param {number} index_
1109      */
1110     es3fUniformApiTests.BasicUniformReportGL = function(name_, nameLength_, size_, type_, index_) {
1111         this.name = name_;
1112         this.nameLength = nameLength_;
1113         this.size = size_;
1114         this.type = type_;
1115         this.index = index_;
1116     };
1118     /**
1119      * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} vec
1120      * @param {string} name
1121      * @return {es3fUniformApiTests.BasicUniformReportGL}
1122      */
1123     es3fUniformApiTests.BasicUniformReportGL.findWithName = function(vec, name) {
1124         for (var i = 0; i < vec.length; i++) {
1125             if (vec[i].name == name)
1126                 return vec[i];
1127         }
1128         return null;
1129     };
1131     /**
1132      * es3fUniformApiTests.UniformCase class, inherits from TestCase class
1133      * @constructor
1134      * @param {string} name
1135      * @param {string} description
1136      * @extends {tcuTestCase.DeqpTest}
1137      */
1138     es3fUniformApiTests.UniformCase = function(name, description) { // \note Randomizes caseType, uniformCollection and features.
1139         tcuTestCase.DeqpTest.call(this, name, description);
1141         /** @type {es3fUniformApiTests.Feature} */ this.m_features;
1142         /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ this.m_uniformCollection;
1144         /** @type {number} */ this.m_caseShaderType = 0;
1146         /** @type {Array<gluTexture.Texture2D>} */ this.m_textures2d = [];
1147         /** @type {Array<gluTexture.TextureCube>} */ this.m_texturesCube = [];
1148         /** @type {Array<number>} */ this.m_filledTextureUnits = [];
1149     };
1151     es3fUniformApiTests.UniformCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
1152     /** es3fUniformApiTests.UniformCase prototype restore */
1153     es3fUniformApiTests.UniformCase.prototype.constructor = es3fUniformApiTests.UniformCase;
1155     /**
1156      * es3fUniformApiTests.UniformCase newC. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
1157      * @param {number} seed
1158      * @return {es3fUniformApiTests.UniformCase}
1159      */
1160     es3fUniformApiTests.UniformCase.prototype.newC = function(seed) {
1161         this.m_features = this.randomFeatures(seed);
1162         this.m_uniformCollection = es3fUniformApiTests.UniformCollection.random(seed);
1163         this.m_caseShaderType = es3fUniformApiTests.randomCaseShaderType(seed);
1165         return this;
1166     };
1168     /**
1169      * es3fUniformApiTests.UniformCase new_B (static). Creates a es3fUniformApiTests.UniformCase
1170      * @param {string} name
1171      * @param {string} description
1172      * @param {number} seed
1173      * @return {es3fUniformApiTests.UniformCase}
1174      */
1175     es3fUniformApiTests.UniformCase.new_C = function(name, description, seed) {
1176         var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newC(seed);
1178         return uniformCase;
1179     };
1181     /**
1182      * es3fUniformApiTests.UniformCase new_B. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
1183      * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
1184      * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
1185      * @param {es3fUniformApiTests.Feature} features
1186      * @return {es3fUniformApiTests.UniformCase}
1187      */
1188     es3fUniformApiTests.UniformCase.prototype.newB = function(caseShaderType, uniformCollection, features) {
1189         this.m_caseShaderType = caseShaderType;
1190         this.m_uniformCollection = uniformCollection;
1191         this.m_features = features;
1193         return this;
1194     };
1196     /**
1197      * es3fUniformApiTests.UniformCase new_B (static). Creates a es3fUniformApiTests.UniformCase
1198      * @param {string} name
1199      * @param {string} description
1200      * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
1201      * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
1202      * @param {es3fUniformApiTests.Feature} features
1203      * @return {es3fUniformApiTests.UniformCase}
1204      */
1205     es3fUniformApiTests.UniformCase.new_B = function(name, description, caseShaderType, uniformCollection, features) {
1206         var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newB(caseShaderType, uniformCollection, features);
1208         return uniformCase;
1209     };
1211     /**
1212      * es3fUniformApiTests.UniformCase new_A. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
1213      * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
1214      * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
1215      * @return {es3fUniformApiTests.UniformCase}
1216      */
1217     es3fUniformApiTests.UniformCase.prototype.newA = function(caseShaderType, uniformCollection) {
1218        this.m_caseShaderType = caseShaderType;
1219        this.m_uniformCollection = uniformCollection;
1220        this.m_features = null;
1222        return this;
1223     };
1225     /**
1226      * es3fUniformApiTests.UniformCase new_A (static). Creates a es3fUniformApiTests.UniformCase
1227      * @param {string} name
1228      * @param {string} description
1229      * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
1230      * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
1231      * @return {es3fUniformApiTests.UniformCase}
1232      */
1233     es3fUniformApiTests.UniformCase.new_A = function(name, description, caseShaderType, uniformCollection) {
1234         var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newA(caseShaderType, uniformCollection);
1236         return uniformCase;
1237     };
1239     /**
1240      * @param {number} seed
1241      * @return {es3fUniformApiTests.Feature}
1242      */
1243     es3fUniformApiTests.UniformCase.prototype.randomFeatures = function(seed) {
1244         /** @type {es3fUniformApiTests.Feature} */ var result = new es3fUniformApiTests.Feature();
1246         /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
1248         result.ARRAYUSAGE_ONLY_MIDDLE_INDEX = rnd.getBool();
1249         result.UNIFORMFUNC_VALUE = rnd.getBool();
1250         result.MATRIXMODE_ROWMAJOR = rnd.getBool();
1251         result.ARRAYASSIGN_FULL = rnd.getBool();
1252         result.ARRAYASSIGN_BLOCKS_OF_TWO = !result.ARRAYASSIGN_FULL;
1253         result.UNIFORMUSAGE_EVERY_OTHER = rnd.getBool();
1254         result.BOOLEANAPITYPE_INT = rnd.getBool();
1255         result.BOOLEANAPITYPE_UINT = !result.BOOLEANAPITYPE_INT;
1256         result.UNIFORMVALUE_ZERO = rnd.getBool();
1258         return result;
1259     };
1261     /**
1262      * Initialize the es3fUniformApiTests.UniformCase
1263      */
1264     es3fUniformApiTests.UniformCase.prototype.init = function() {
1265         /** @type {number} */ var numSamplerUniforms = this.m_uniformCollection.getNumSamplers();
1266         /** @type {number} */ var vertexTexUnitsRequired = this.m_caseShaderType != es3fUniformApiTests.CaseShaderType.FRAGMENT ? numSamplerUniforms : 0;
1267         /** @type {number} */ var fragmentTexUnitsRequired = this.m_caseShaderType != es3fUniformApiTests.CaseShaderType.VERTEX ? numSamplerUniforms : 0;
1268         /** @type {number} */ var combinedTexUnitsRequired = vertexTexUnitsRequired + fragmentTexUnitsRequired;
1269         var vertexTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS));
1270         var fragmentTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
1271         var combinedTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
1273         assertMsgOptions(
1274             numSamplerUniforms <= es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS,
1275             'es3fUniformApiTests.UniformCase.prototype.init - sampler uniforms exceed MAX_NUM_SAMPLER_UNIFORMS',
1276             false,
1277             true
1278         );
1280         if (vertexTexUnitsRequired > vertexTexUnitsSupported)
1281             testFailedOptions('' + vertexTexUnitsRequired + ' vertex texture units required, ' + vertexTexUnitsSupported + ' supported', true);
1282         if (fragmentTexUnitsRequired > fragmentTexUnitsSupported)
1283             testFailedOptions('' + fragmentTexUnitsRequired + ' fragment texture units required, ' + fragmentTexUnitsSupported + ' supported', true);
1284         if (combinedTexUnitsRequired > combinedTexUnitsSupported)
1285             testFailedOptions('' + combinedTexUnitsRequired + ' combined texture units required, ' + combinedTexUnitsSupported + ' supported', true);
1286     };
1288     /**
1289      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniformsDst
1290      * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsDst
1291      * @param {gluVarType.VarType} varType
1292      * @param {string} varName
1293      * @param {boolean} isParentActive
1294      * @param {number} samplerUnitCounter
1295      * @param {deRandom.Random} rnd
1296      * @return {number} Used to be output parameter. Sampler unit count
1297      */
1298     es3fUniformApiTests.UniformCase.prototype.generateBasicUniforms = function(basicUniformsDst, basicUniformReportsDst, varType, varName, isParentActive, samplerUnitCounter, rnd) {
1299         /** @type {es3fUniformApiTests.VarValue} */ var value;
1301         if (varType.isBasicType()) {
1302             /** @type {boolean} */ var isActive = isParentActive && (this.m_features.UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.length % 2 == 0 : true);
1303             /** @type {gluShaderUtil.DataType} */ var type = varType.getBasicType();
1304             value = this.m_features.UNIFORMVALUE_ZERO ? es3fUniformApiTests.generateZeroVarValue(type) :
1305             gluShaderUtil.isDataTypeSampler(type) ? es3fUniformApiTests.generateRandomVarValue(type, rnd, samplerUnitCounter++) :
1306                                                 es3fUniformApiTests.generateRandomVarValue(varType.getBasicType(), rnd);
1308             basicUniformsDst.push(new es3fUniformApiTests.BasicUniform(varName, varType.getBasicType(), isActive, value));
1309             basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportRef(varName, varType.getBasicType(), isActive));
1310         } else if (varType.isArrayType()) {
1311             /** @type {number} */ var size = varType.getArraySize();
1312             /** @type {string} */ var arrayRootName = '' + varName + '[0]';
1313             /** @type {Array<boolean>} */ var isElemActive = [];
1315             for (var elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++) {
1316                 /** @type {string} */ var indexedName = '' + varName + '[' + elemNdx + ']';
1317                 /** @type {boolean} */ var isCurElemActive = isParentActive &&
1318                                                   (this.m_features.UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.length % 2 == 0 : true) &&
1319                                                   (this.m_features.ARRAYUSAGE_ONLY_MIDDLE_INDEX ? elemNdx == Math.floor(size / 2) : true);
1321                 isElemActive.push(isCurElemActive);
1323                 if (varType.getElementType().isBasicType()) {
1324                     // \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays.
1325                     /** @type {gluShaderUtil.DataType} */ var elemBasicType = varType.getElementType().getBasicType();
1326                     value = this.m_features.UNIFORMVALUE_ZERO ? es3fUniformApiTests.generateZeroVarValue(elemBasicType) :
1327                     gluShaderUtil.isDataTypeSampler(elemBasicType) ? es3fUniformApiTests.generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++) :
1328                                                         es3fUniformApiTests.generateRandomVarValue(elemBasicType, rnd);
1330                     basicUniformsDst.push(new es3fUniformApiTests.BasicUniform(indexedName, elemBasicType, isCurElemActive, value, arrayRootName, elemNdx, size));
1331                 } else
1332                     samplerUnitCounter = this.generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName, isCurElemActive, samplerUnitCounter, rnd);
1333             }
1335             if (varType.getElementType().isBasicType()) {
1336                 /** @type {number} */ var minSize;
1337                 for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize - 1]; minSize--) {}
1339                 basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportRef(arrayRootName, varType.getElementType().getBasicType(), isParentActive && minSize > 0).constructor_A(minSize, size));
1340             }
1341         } else {
1342             assertMsgOptions(
1343                 varType.isStructType(),
1344                 'es3fUniformApiTests.UniformCase.prototype.generateBasicUniforms - not a struct type',
1345                 false,
1346                 true
1347             );
1349             /** @type {gluVarType.StructType} */ var structType = varType.getStruct();
1351             for (var i = 0; i < structType.getSize(); i++) {
1352                 /** @type {gluVarType.StructMember} */ var member = structType.getMember(i);
1353                 /** @type {string} */ var memberFullName = '' + varName + '.' + member.getName();
1355                 samplerUnitCounter = this.generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName, isParentActive, samplerUnitCounter, rnd);
1356             }
1357         }
1359         return samplerUnitCounter;
1360     };
1362     /**
1363      * @param {string} dst
1364      * @return {string}
1365      */
1366     es3fUniformApiTests.UniformCase.prototype.writeUniformDefinitions = function(dst) {
1367         for (var i = 0; i < this.m_uniformCollection.getNumStructTypes(); i++)
1368             dst += gluVarType.declareStructType(this.m_uniformCollection.getStructType(i), 0) + ';\n';
1370         for (var i = 0; i < this.m_uniformCollection.getNumUniforms(); i++)
1371             dst += 'uniform ' + gluVarType.declareVariable(this.m_uniformCollection.getUniform(i).type, this.m_uniformCollection.getUniform(i).name, 0) + ';\n';
1373         dst += '\n';
1375         var compareFuncs = [{
1376                 requiringTypes: [gluShaderUtil.isDataTypeFloatOrVec, gluShaderUtil.isDataTypeMatrix],
1377                 definition: 'mediump float compare_float (mediump float a, mediump float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }'
1378             },{
1379                 requiringTypes: [
1380                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC2, t);},
1381                     function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(2, t);}
1382                 ],
1383                 definition: 'mediump float compare_vec2 (mediump vec2 a, mediump vec2 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }'
1384             },{
1385                 requiringTypes: [
1386                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC3, t);},
1387                     function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(3, t);}
1388                 ],
1389                 definition: 'mediump float compare_vec3 (mediump vec3 a, mediump vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }'
1390             },{
1391                 requiringTypes: [
1392                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC4, t);},
1393                     function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(4, t);}],
1394                 definition: 'mediump float compare_vec4 (mediump vec4 a, mediump vec4 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }'
1395             },{
1396                 requiringTypes: [
1397                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2, t);},
1398                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1399                 ],
1400                 definition: 'mediump float compare_mat2 (mediump mat2 a, mediump mat2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }'
1401             },{
1402                 requiringTypes: [
1403                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2X3, t);},
1404                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1405                 ],
1406                 definition: 'mediump float compare_mat2x3 (mediump mat2x3 a, mediump mat2x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }'
1407             },{
1408                 requiringTypes: [
1409                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2X4, t);},
1410                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1411                 ],
1412                 definition: 'mediump float compare_mat2x4 (mediump mat2x4 a, mediump mat2x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }'
1413             },{
1414                 requiringTypes: [
1415                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3X2, t);},
1416                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1417                 ],
1418                 definition: 'mediump float compare_mat3x2 (mediump mat3x2 a, mediump mat3x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }'
1419             },{
1420                 requiringTypes: [
1421                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3, t);},
1422                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1423                 ],
1424                 definition: 'mediump float compare_mat3 (mediump mat3 a, mediump mat3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }'
1425             },{
1426                 requiringTypes: [
1427                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3X4, t);},
1428                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1429                 ],
1430                 definition: 'mediump float compare_mat3x4 (mediump mat3x4 a, mediump mat3x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }'
1431             },{
1432                 requiringTypes: [
1433                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4X2, t);},
1434                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1435                 ],
1436                 definition: 'mediump float compare_mat4x2 (mediump mat4x2 a, mediump mat4x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }'
1437             },{
1438                 requiringTypes: [
1439                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4X3, t);},
1440                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1441                 ],
1442                 definition: 'mediump float compare_mat4x3 (mediump mat4x3 a, mediump mat4x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }'
1443             },{
1444                 requiringTypes: [
1445                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4, t);},
1446                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1447                 ],
1448                 definition: 'mediump float compare_mat4 (mediump mat4 a, mediump mat4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }'
1449             },{
1450                 requiringTypes: [
1451                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT, t);},
1452                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1453                 ],
1454                 definition: 'mediump float compare_int (mediump int a, mediump int b) { return a == b ? 1.0 : 0.0; }'
1455             },{
1456                 requiringTypes: [
1457                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC2, t);},
1458                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1459                 ],
1460                 definition: 'mediump float compare_ivec2 (mediump ivec2 a, mediump ivec2 b) { return a == b ? 1.0 : 0.0; }'
1461             },{
1462                 requiringTypes: [
1463                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC3, t);},
1464                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1465                 ],
1466                 definition: 'mediump float compare_ivec3 (mediump ivec3 a, mediump ivec3 b) { return a == b ? 1.0 : 0.0; }'
1467             },{
1468                 requiringTypes: [
1469                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC4, t);},
1470                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1471                 ],
1472                 definition: 'mediump float compare_ivec4 (mediump ivec4 a, mediump ivec4 b) { return a == b ? 1.0 : 0.0; }'
1473             },{
1474                 requiringTypes: [
1475                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT, t);},
1476                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1477                 ],
1478                 definition: 'mediump float compare_uint (mediump uint a, mediump uint b) { return a == b ? 1.0 : 0.0; }'
1479             },{
1480                 requiringTypes: [
1481                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC2, t);},
1482                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1483                 ],
1484                 definition: 'mediump float compare_uvec2 (mediump uvec2 a, mediump uvec2 b) { return a == b ? 1.0 : 0.0; }'
1485             },{
1486                 requiringTypes: [
1487                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC3, t);},
1488                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1489                 ],
1490                 definition: 'mediump float compare_uvec3 (mediump uvec3 a, mediump uvec3 b) { return a == b ? 1.0 : 0.0; }'
1491             },{
1492                 requiringTypes: [
1493                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC4, t);},
1494                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1495                 ],
1496                 definition: 'mediump float compare_uvec4 (mediump uvec4 a, mediump uvec4 b) { return a == b ? 1.0 : 0.0; }'
1497             },{
1498                 requiringTypes: [
1499                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL, t);},
1500                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1501                 ],
1502                 definition: 'mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }'
1503             },{
1504                 requiringTypes: [
1505                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC2, t);},
1506                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1507                 ],
1508                 definition: 'mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }'
1509             },{
1510                 requiringTypes: [
1511                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC3, t);},
1512                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1513                 ],
1514                 definition: 'mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }'
1515             },{
1516                 requiringTypes: [
1517                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC4, t);},
1518                     function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
1519                 ],
1520                 definition: 'mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }'
1521             }
1522         ];
1524         /** @type {Array<gluShaderUtil.DataType>} */ var samplerTypes = this.m_uniformCollection.getSamplerTypes();
1526         for (var compFuncNdx = 0; compFuncNdx < compareFuncs.length; compFuncNdx++) {
1527             /** @type {Array<es3fUniformApiTests.dataTypePredicate>} */ var typeReq = compareFuncs[compFuncNdx].requiringTypes;
1528             /** @type {boolean} */ var containsTypeSampler = false;
1530             for (var i = 0; i < samplerTypes.length; i++) {
1531                 if (gluShaderUtil.isDataTypeSampler(samplerTypes[i])) {
1532                     /** @type {gluShaderUtil.DataType} */ var retType = es3fUniformApiTests.getSamplerLookupReturnType(samplerTypes[i]);
1533                     if (typeReq[0](retType) || typeReq[1](retType)) {
1534                         containsTypeSampler = true;
1535                         break;
1536                     }
1537                 }
1538             }
1540             if (containsTypeSampler || this.m_uniformCollection.containsMatchingBasicType(typeReq[0]) || this.m_uniformCollection.containsMatchingBasicType(typeReq[1]))
1541                 dst += compareFuncs[compFuncNdx].definition + '\n';
1542         }
1544         return dst;
1545     };
1547     /**
1548      * @param {string} dst
1549      * @param {es3fUniformApiTests.BasicUniform} uniform
1550      * @return {string} Used to write the string in the output parameter
1551      */
1552     es3fUniformApiTests.UniformCase.prototype.writeUniformCompareExpr = function(dst, uniform) {
1553         if (gluShaderUtil.isDataTypeSampler(uniform.type))
1554             dst += 'compare_' + gluShaderUtil.getDataTypeName(es3fUniformApiTests.getSamplerLookupReturnType(uniform.type)) + '(texture(' + uniform.name + ', vec' + es3fUniformApiTests.getSamplerNumLookupDimensions(uniform.type) + '(0.0))'; //WebGL2.0
1555         else
1556             dst += 'compare_' + gluShaderUtil.getDataTypeName(uniform.type) + '(' + uniform.name;
1558         dst += ', ' + es3fUniformApiTests.shaderVarValueStr(uniform.finalValue) + ')';
1560         return dst;
1561     };
1563     /**
1564      * @param {string} dst
1565      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
1566      * @param {string} variableName
1567      * @return {string} Used to write the string in the output parameter
1568      */
1569     es3fUniformApiTests.UniformCase.prototype.writeUniformComparisons = function(dst, basicUniforms, variableName) {
1570         for (var i = 0; i < basicUniforms.length; i++) {
1571             /** @type {es3fUniformApiTests.BasicUniform} */ var unif = basicUniforms[i];
1573             if (unif.isUsedInShader) {
1574                 dst += '\t' + variableName + ' *= ';
1575                 dst = this.writeUniformCompareExpr(dst, basicUniforms[i]);
1576                 dst += ';\n';
1577             } else
1578                 dst += '\t// UNUSED: ' + basicUniforms[i].name + '\n';
1579         }
1581         return dst;
1582     };
1584     /**
1585      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
1586      * @return {string}
1587      */
1588     es3fUniformApiTests.UniformCase.prototype.generateVertexSource = function(basicUniforms) {
1589         /** @type {boolean} */ var isVertexCase = this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.VERTEX || this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.BOTH;
1590         /** @type {string} */ var result = '';
1592         result += '#version 300 es\n' +
1593                   'in highp vec4 a_position;\n' +
1594                   'out mediump float v_vtxOut;\n' +
1595                   '\n';
1597         if (isVertexCase)
1598             result = this.writeUniformDefinitions(result);
1600         result += '\n' +
1601                   'void main (void)\n' +
1602                   ' {\n' +
1603                   ' gl_Position = a_position;\n' +
1604                   ' v_vtxOut = 1.0;\n';
1606         if (isVertexCase)
1607             result = this.writeUniformComparisons(result, basicUniforms, 'v_vtxOut');
1609         result += '}\n';
1611         return result;
1612     };
1614     /**
1615      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
1616      * @return {string}
1617      */
1618     es3fUniformApiTests.UniformCase.prototype.generateFragmentSource = function(basicUniforms) {
1619         /**@type {boolean} */ var isFragmentCase = this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.FRAGMENT || this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.BOTH;
1620         /**@type {string} */ var result = '';
1622         result += '#version 300 es\n' +
1623                   'in mediump float v_vtxOut;\n' +
1624                   '\n';
1626         if (isFragmentCase)
1627             result = this.writeUniformDefinitions(result);
1629         result += '\n' +
1630                   'layout(location = 0) out mediump vec4 dEQP_FragColor;\n' +
1631                   '\n' +
1632                   'void main (void)\n' +
1633                   ' {\n' +
1634                   ' mediump float result = v_vtxOut;\n';
1636         if (isFragmentCase)
1637             result = this.writeUniformComparisons(result, basicUniforms, 'result');
1639         result += ' dEQP_FragColor = vec4(result, result, result, 1.0);\n' +
1640                   '}\n';
1642         return result;
1643     };
1645     /**
1646      * @param {es3fUniformApiTests.VarValue} value
1647      */
1648     es3fUniformApiTests.UniformCase.prototype.setupTexture = function(value) {
1649         // \note No handling for samplers other than 2D or cube.
1651         assertMsgOptions(
1652             es3fUniformApiTests.getSamplerLookupReturnType(value.type) == gluShaderUtil.DataType.FLOAT_VEC4,
1653             'es3fUniformApiTests.UniformCase.prototype.setupTexture - sampler return type should be vec4f', false, true
1654         );
1656         /** @type {number} */ var width = 32;
1657         /** @type {number} */ var height = 32;
1658         /** @type {Array<number>} */ var color = value.val.samplerV.fillColor;
1659         /** @type {tcuTexture.TextureCube} */ var refTexture;
1660         /** @type {gluTexture.TextureCube} */ var texture;
1662         if (value.type == gluShaderUtil.DataType.SAMPLER_2D) {
1663             texture = gluTexture.texture2DFromFormat(gl, gl.RGBA, gl.UNSIGNED_BYTE, width, height);
1664             refTexture = texture.getRefTexture();
1665             this.m_textures2d.push(texture);
1667             refTexture.allocLevel(0);
1668             es3fUniformApiTests.fillWithColor(refTexture.getLevel(0), color);
1670            gl.activeTexture(gl.TEXTURE0 + value.val.samplerV.unit);
1671             this.m_filledTextureUnits.push(value.val.samplerV.unit);
1672             texture.upload();
1673            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
1674            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1675            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
1676            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
1677         } else if (value.type == gluShaderUtil.DataType.SAMPLER_CUBE) {
1678             assertMsgOptions(width == height, 'es3fUniformApiTests.UniformCase.prototype.setupTexture - non square texture', false, true);
1680             texture = gluTexture.cubeFromFormat(gl, gl.RGBA, gl.UNSIGNED_BYTE, width);
1681             refTexture = texture.getRefTexture();
1682             this.m_texturesCube.push(texture);
1684             for (var face in tcuTexture.CubeFace) {
1685                 refTexture.allocLevel(tcuTexture.CubeFace[face], 0);
1686                 es3fUniformApiTests.fillWithColor(refTexture.getLevelFace(0, tcuTexture.CubeFace[face]), color);
1687             }
1689            gl.activeTexture(gl.TEXTURE0 + value.val.samplerV.unit);
1690             this.m_filledTextureUnits.push(value.val.samplerV.unit);
1691             texture.upload();
1692            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
1693            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1694            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
1695            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
1696         } else
1697             throw new Error('es3fUniformApiTests.UniformCase.prototype.setupTexture - Invalid sampler type');
1698     };
1700     /**
1701      * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} basicUniformReportsDst
1702      * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
1703      * @param {WebGLProgram} programGL
1704      * @return {boolean}
1705      */
1706     es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne = function(basicUniformReportsDst, basicUniformReportsRef, programGL) {
1707         /** @type {WebGLProgram} */ var numActiveUniforms;
1708         /** @type {boolean} */ var success = true;
1710        numActiveUniforms = /** @type {WebGLProgram} */ (gl.getProgramParameter(programGL, gl.ACTIVE_UNIFORMS));
1711         bufferedLogToConsole('// Number of active uniforms reported: ' + numActiveUniforms);
1713         for (var unifNdx = 0; unifNdx < numActiveUniforms; unifNdx++) {
1714             /** @type {number} (GLint)*/ var reportedSize = -1;
1715             /** @type {number} (GLenum)*/ var reportedTypeGL = gl.NONE;
1716             /** @type {gluShaderUtil.DataType} */ var reportedType;
1717             /** @type {string} */ var reportedNameStr;
1718             /** @type {WebGLActiveInfo} */ var activeInfo;
1720            activeInfo = gl.getActiveUniform(programGL, unifNdx);
1722             reportedNameStr = activeInfo.name;
1723             reportedTypeGL = activeInfo.type;
1724             reportedSize = activeInfo.size;
1726             reportedType = gluShaderUtil.getDataTypeFromGLType(reportedTypeGL);
1728             checkMessage(reportedType !== undefined, 'Invalid uniform type');
1730             bufferedLogToConsole('// Got name = ' + reportedNameStr + ', size = ' + reportedSize + ', type = ' + gluShaderUtil.getDataTypeName(reportedType));
1732             // Ignore built-in uniforms.
1733             if (reportedNameStr.indexOf('gl_') == -1) {
1734                 /** @type {number} */ var referenceNdx;
1735                 for (referenceNdx = 0; referenceNdx < basicUniformReportsRef.length; referenceNdx++) {
1736                     if (basicUniformReportsRef[referenceNdx].name == reportedNameStr)
1737                         break;
1738                 }
1740                 if (referenceNdx >= basicUniformReportsRef.length) {
1741                     bufferedLogToConsole('// FAILURE: invalid non-built-in uniform name reported');
1742                     success = false;
1743                 } else {
1744                     /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var reference = basicUniformReportsRef[referenceNdx];
1746                     assertMsgOptions(
1747                         reference.type !== undefined,
1748                         'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - type is undefined',
1749                         false,
1750                         true
1751                     );
1752                     assertMsgOptions(
1753                         reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader),
1754                         'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - uniform min size does not match usage in shader',
1755                         false,
1756                         true
1757                     );
1758                     assertMsgOptions(
1759                         reference.minSize <= reference.maxSize,
1760                         'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - uniform min size bigger than max size',
1761                         false,
1762                         true
1763                     );
1765                     if (es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, reportedNameStr) !== null) {
1766                         bufferedLogToConsole('// FAILURE: same uniform name reported twice');
1767                         success = false;
1768                     }
1770                     basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportGL(reportedNameStr, reportedNameStr.length, reportedSize, reportedType, unifNdx));
1772                     if (reportedType != reference.type) {
1773                         bufferedLogToConsole('// FAILURE: wrong type reported, should be ' + gluShaderUtil.getDataTypeName(reference.type));
1774                         success = false;
1775                     }
1776                     if (reportedSize < reference.minSize || reportedSize > reference.maxSize) {
1777                         bufferedLogToConsole('// FAILURE: wrong size reported, should be ' +
1778                             (reference.minSize == reference.maxSize ? reference.minSize : 'in the range [' + reference.minSize + ', ' + reference.maxSize + ']'));
1780                         success = false;
1781                     }
1782                 }
1783             }
1784         }
1786         for (var i = 0; i < basicUniformReportsRef.length; i++) {
1787             /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var expected = basicUniformReportsRef[i];
1788             if (expected.isUsedInShader && es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, expected.name) === null) {
1789                 bufferedLogToConsole('// FAILURE: uniform with name ' + expected.name + ' was not reported by GL');
1790                 success = false;
1791             }
1792         }
1794         return success;
1795     };
1797     /**
1798      * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} basicUniformReportsDst
1799      * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
1800      * @param {WebGLProgram} programGL
1801      * @return {boolean}
1802      */
1803     es3fUniformApiTests.UniformCase.prototype.getActiveUniforms = function(basicUniformReportsDst, basicUniformReportsRef, programGL) {
1804         /** @type {Array<string>} */ var queryNames = new Array(basicUniformReportsRef.length);
1805         /** @type {Array<string>} */ var queryNamesC = new Array(basicUniformReportsRef.length);
1806         /** @type {Array<number>} (GLuint) */ var uniformIndices = new Array(basicUniformReportsRef.length);
1807         /** @type {Array<number>} */ var validUniformIndices = []; // This shall have the same contents, and in same order, as uniformIndices, but with gl.INVALID_INDEX entries removed.
1808         /** @type {boolean} */ var success = true;
1810         for (var i = 0; i < basicUniformReportsRef.length; i++) {
1811             /** @type {string} */ var name = basicUniformReportsRef[i].name;
1812             queryNames[i] = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && name[name.length - 1] == ']' ? es3fUniformApiTests.beforeLast(name, '[') : name;
1813             queryNamesC[i] = queryNames[i];
1814         }
1816        uniformIndices = gl.getUniformIndices(programGL, queryNamesC);
1818         for (var i = 0; i < uniformIndices.length; i++) {
1819             if (uniformIndices[i] != gl.INVALID_INDEX)
1820                 validUniformIndices.push(uniformIndices[i]);
1821             else {
1822                 if (basicUniformReportsRef[i].isUsedInShader) {
1823                     bufferedLogToConsole('// FAILURE: uniform with name ' + basicUniformReportsRef[i].name + ' received gl.INVALID_INDEX');
1824                     success = false;
1825                 }
1826             }
1827         }
1829         if (validUniformIndices.length > 0) {
1830             /** @type {Array<string>} */ var uniformNameBuf = new Array(validUniformIndices.length);
1831             /** @type {Array<number>} (GLint) */ var uniformSizeBuf = new Array(validUniformIndices.length);
1832             /** @type {Array<number>} (GLint) */ var uniformTypeBuf = new Array(validUniformIndices.length);
1834            uniformSizeBuf = gl.getActiveUniforms(programGL, validUniformIndices, gl.UNIFORM_SIZE);
1835            uniformTypeBuf = gl.getActiveUniforms(programGL, validUniformIndices, gl.UNIFORM_TYPE);
1837             /** @type {number} */ var validNdx = -1; // Keeps the corresponding index to validUniformIndices while unifNdx is the index to uniformIndices.
1838             for (var unifNdx = 0; unifNdx < uniformIndices.length; unifNdx++) {
1839                 if (uniformIndices[unifNdx] == gl.INVALID_INDEX)
1840                     continue;
1842                 validNdx++;
1844                 /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var reference = basicUniformReportsRef[unifNdx];
1845                 /** @type {number} */ var reportedIndex = validUniformIndices[validNdx];
1846                 /** @type {number} */ var reportedNameLength = reference.name.length;
1847                 /** @type {number} */ var reportedSize = uniformSizeBuf[validNdx];
1848                 /** @type {gluShaderUtil.DataType} */ var reportedType = gluShaderUtil.getDataTypeFromGLType(uniformTypeBuf[validNdx]);
1849                 /** @type {string} */ var reportedNameStr = reference.name;
1851                 bufferedLogToConsole('// Got name size = ' + reportedSize +
1852                     ', type = ' + gluShaderUtil.getDataTypeName(reportedType) +
1853                     ' for the uniform at index ' + reportedIndex + ' (' + reference.name + ')');
1855                 assertMsgOptions(
1856                     reference.type !== undefined,
1857                     'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - type is undefined',
1858                     false,
1859                     true
1860                 );
1861                 assertMsgOptions(
1862                     reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader),
1863                     'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - uniform min size does not match usage in shader',
1864                     false,
1865                     true
1866                 );
1867                 assertMsgOptions(
1868                     reference.minSize <= reference.maxSize,
1869                     'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - uniform min size bigger than max size',
1870                     false,
1871                     true
1872                 );
1874                 if (es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, reportedNameStr) !== null) {
1875                     bufferedLogToConsole('// FAILURE: same uniform name reported twice');
1876                     success = false;
1877                 }
1878                 basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportGL(reference.name, reportedNameLength, reportedSize, reportedType, reportedIndex));
1880                 if (reportedType != reference.type) {
1881                     bufferedLogToConsole('// FAILURE: wrong type reported, should be ' + gluShaderUtil.getDataTypeName(reference.type));
1882                     success = false;
1883                 }
1885                 if (reportedSize < reference.minSize || reportedSize > reference.maxSize) {
1886                     bufferedLogToConsole('// FAILURE: wrong size reported, should be ' +
1887                         (reference.minSize == reference.maxSize ? reference.minSize : 'in the range [' + reference.minSize + ', ' + reference.maxSize + ']'));
1889                     success = false;
1890                 }
1891             }
1892         }
1894         return success;
1895     };
1897     /**
1898      * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} uniformResults
1899      * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} uniformsResults
1900      * @return {boolean}
1901      */
1902     es3fUniformApiTests.UniformCase.prototype.uniformVsUniformsComparison = function(uniformResults, uniformsResults) {
1903         /** @type {boolean} */ var success = true;
1904         /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformsResult;
1906         for (var uniformResultNdx = 0; uniformResultNdx < uniformResults.length; uniformResultNdx++) {
1907             /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformResult = uniformResults[uniformResultNdx];
1908             /** @type {string} */ var uniformName = uniformResult.name;
1909             uniformsResult = es3fUniformApiTests.BasicUniformReportGL.findWithName(uniformsResults, uniformName);
1911             if (uniformsResult !== null) {
1912                 bufferedLogToConsole('// Checking uniform ' + uniformName);
1914                 if (uniformResult.index != uniformsResult.index) {
1915                     bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetUniformIndices() gave different indices for uniform ' + uniformName);
1916                     success = false;
1917                 }
1918                 if (uniformResult.nameLength != uniformsResult.nameLength) {
1919                     bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave incompatible name lengths for uniform ' + uniformName);
1920                     success = false;
1921                 }
1922                 if (uniformResult.size != uniformsResult.size) {
1923                     bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave different sizes for uniform ' + uniformName);
1924                     success = false;
1925                 }
1926                 if (uniformResult.type != uniformsResult.type) {
1927                     bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave different types for uniform ' + uniformName);
1928                     success = false;
1929                 }
1930             } else {
1931                 bufferedLogToConsole('// FAILURE: uniform ' + uniformName + ' was reported active by glGetActiveUniform() but not by glGetUniformIndices()');
1932                 success = false;
1933             }
1934         }
1936         for (var uniformsResultNdx = 0; uniformsResultNdx < uniformsResults.length; uniformsResultNdx++) {
1937             uniformsResult = uniformsResults[uniformsResultNdx];
1938             /** @type {string} */ var uniformsName = uniformsResult.name;
1939             /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformsResultIt = es3fUniformApiTests.BasicUniformReportGL.findWithName(uniformsResults, uniformsName);
1941             if (uniformsResultIt === null) {
1942                 bufferedLogToConsole('// FAILURE: uniform ' + uniformsName + ' was reported active by glGetUniformIndices() but not by glGetActiveUniform()');
1943                 success = false;
1944             }
1945         }
1947         return success;
1948     };
1950     /**
1951      * @param {Array<es3fUniformApiTests.VarValue>} valuesDst
1952      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
1953      * @param {WebGLProgram} programGL
1954      * @return {boolean}
1955      */
1956     es3fUniformApiTests.UniformCase.prototype.getUniforms = function(valuesDst, basicUniforms, programGL) {
1957         /** @type {boolean} */ var success = true;
1959         for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
1960             /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
1961             /** @type {string} */ var queryName = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? es3fUniformApiTests.beforeLast(uniform.name, '[') : uniform.name;
1962             /** @type {WebGLUniformLocation} */ var location = gl.getUniformLocation(programGL, queryName);
1963             /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(uniform.type);
1964             /** @type {es3fUniformApiTests.VarValue} */ var value = new es3fUniformApiTests.VarValue();
1966             if (!location) {
1967                 value.type = gluShaderUtil.DataType.INVALID;
1968                 valuesDst.push(value);
1969                 if (uniform.isUsedInShader) {
1970                     bufferedLogToConsole('// FAILURE: ' + uniform.name + ' was used in shader, but has location -1');
1971                     success = false;
1972                 }
1973                 continue;
1974             }
1976             value.type = uniform.type;
1978             var result = /** @type {number} */ (gl.getUniform(programGL, location));
1980             if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
1981                 value.val = new es3fUniformApiTests.SamplerV();
1982                 value.val.samplerV.unit = result;
1983             } else
1984                 value.val = /** @type {Array<number>} */ (result.length === undefined ? [result] : result);
1986             valuesDst.push(value);
1988             bufferedLogToConsole('// Got ' + uniform.name + ' value ' + es3fUniformApiTests.apiVarValueStr(value));
1989         }
1991         return success;
1992     };
1994     /**
1995      * @param {Array<es3fUniformApiTests.VarValue>} values
1996      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
1997      * @return {boolean}
1998      */
1999     es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues = function(values, basicUniforms) {
2000         /** @type {boolean} */ var success = true;
2002         assertMsgOptions(
2003             values.length == basicUniforms.length,
2004             'es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues - lengths do not match',
2005             false,
2006             true
2007         );
2009         for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
2010             /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
2011             /** @type {es3fUniformApiTests.VarValue} */ var unifValue = values[unifNdx];
2012             /** @type {number} */ var valSize = gluShaderUtil.getDataTypeScalarSize(uniform.type);
2014             bufferedLogToConsole('// Checking uniform ' + uniform.name);
2016             if (unifValue.type == gluShaderUtil.DataType.INVALID) // This happens when glGetUniformLocation() returned -1.
2017                 continue;
2019             var CHECK_UNIFORM = function(ZERO) {
2020                 do {
2021                     for (var i = 0; i < valSize; i++) {
2022                         if (unifValue.val[i] != ZERO) {
2023                             bufferedLogToConsole('// FAILURE: uniform ' + uniform.name + ' has non-zero initial value');
2024                             success = false;
2025                         }
2026                     }
2027                 } while (false);
2028             };
2030             if (gluShaderUtil.isDataTypeFloatOrVec(uniform.type) || gluShaderUtil.isDataTypeMatrix(uniform.type))
2031                 CHECK_UNIFORM(0.0);
2032             else if (gluShaderUtil.isDataTypeIntOrIVec(uniform.type))
2033                 CHECK_UNIFORM(0);
2034             else if (gluShaderUtil.isDataTypeUintOrUVec(uniform.type))
2035                 CHECK_UNIFORM(0);
2036             else if (gluShaderUtil.isDataTypeBoolOrBVec(uniform.type))
2037                 CHECK_UNIFORM(false);
2038             else if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
2039                 if (unifValue.val.samplerV.unit != 0) {
2040                     bufferedLogToConsole('// FAILURE: uniform ' + uniform.name + ' has non-zero initial value');
2041                     success = false;
2042                 }
2043             } else
2044                 throw new Error('es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues - invalid uniform type');
2045         }
2047         return success;
2048     };
2050     /**
2051      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
2052      * @param {WebGLProgram} programGL
2053      * @param {deRandom.Random} rnd
2054      */
2055     es3fUniformApiTests.UniformCase.prototype.assignUniforms = function(basicUniforms, programGL, rnd) {
2056         /** @type {boolean} */ var transpose = false; //No support to transpose uniform matrices in WebGL, must always be false. (this.m_features.MATRIXMODE_ROWMAJOR) != 0;
2057         /** @type {boolean} (GLboolean) */ var transposeGL = transpose;
2058         /** @type {gluShaderUtil.DataType} */ var boolApiType = this.m_features.BOOLEANAPITYPE_INT ? gluShaderUtil.DataType.INT :
2059                                                 this.m_features.BOOLEANAPITYPE_UINT ? gluShaderUtil.DataType.UINT :
2060                                                 gluShaderUtil.DataType.FLOAT;
2062         for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
2063             /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
2064             /** @type {boolean} */ var isArrayMember = uniform.elemNdx >= 0;
2065             /** @type {string} */ var queryName = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? es3fUniformApiTests.beforeLast(uniform.name, '[') : uniform.name;
2066             /** @type {number} */ var numValuesToAssign = !isArrayMember ? 1 :
2067                                                         this.m_features.ARRAYASSIGN_FULL ? (uniform.elemNdx == 0 ? uniform.rootSize : 0) :
2068                                                         this.m_features.ARRAYASSIGN_BLOCKS_OF_TWO ? (uniform.elemNdx % 2 == 0 ? 2 : 0) :
2069                                                         /* Default: assign array elements separately */ 1;
2071             assertMsgOptions(
2072                 numValuesToAssign >= 0,
2073                 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - number of values to assign not a positive integer',
2074                 false,
2075                 true
2076             );
2077             assertMsgOptions(
2078                 numValuesToAssign == 1 || isArrayMember,
2079                 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - not an array member and number of values to assign not 1',
2080                 false,
2081                 true
2082             );
2084             if (numValuesToAssign == 0) {
2085                 bufferedLogToConsole('// es3fUniformApiTests.Uniform ' + uniform.name + ' is covered by another glUniform*v() call to the same array');
2086                 continue;
2087             }
2089             /** @type {WebGLUniformLocation} */ var location = gl.getUniformLocation(programGL, queryName);
2090             /** @type {number} */ var typeSize = gluShaderUtil.getDataTypeScalarSize(uniform.type);
2091             /** @type {boolean} */ var assignByValue = this.m_features.UNIFORMFUNC_VALUE && !gluShaderUtil.isDataTypeMatrix(uniform.type) && numValuesToAssign == 1;
2092             /** @type {Array<es3fUniformApiTests.VarValue>} */ var valuesToAssign = [];
2093             /** @type {Array<number>} */ var buffer;
2095             for (var i = 0; i < numValuesToAssign; i++) {
2096                 /** @type {string} */ var curName = isArrayMember ? es3fUniformApiTests.beforeLast(uniform.rootName, '[') + '[' + (uniform.elemNdx + i) + ']' : uniform.name;
2097                 /** @type {es3fUniformApiTests.VarValue} */ var unifValue = new es3fUniformApiTests.VarValue();
2099                 if (isArrayMember) {
2100                     /** @type {es3fUniformApiTests.BasicUniform} */ var elemUnif = es3fUniformApiTests.BasicUniform.findWithName(basicUniforms, curName);
2101                     if (elemUnif === null)
2102                         continue;
2103                     unifValue = elemUnif.finalValue;
2104                 } else
2105                     unifValue = uniform.finalValue;
2107                 /** @type {es3fUniformApiTests.VarValue} */ var apiValue = gluShaderUtil.isDataTypeBoolOrBVec(unifValue.type) ? es3fUniformApiTests.getRandomBoolRepresentation(unifValue, boolApiType, rnd) :
2108                 gluShaderUtil.isDataTypeSampler(unifValue.type) ? es3fUniformApiTests.getSamplerUnitValue(unifValue) :
2109                                         unifValue;
2111                 valuesToAssign.push(gluShaderUtil.isDataTypeMatrix(apiValue.type) && transpose ? es3fUniformApiTests.getTransposeMatrix(apiValue) : apiValue);
2113                 if (gluShaderUtil.isDataTypeBoolOrBVec(uniform.type))
2114                     bufferedLogToConsole('// Using type ' + gluShaderUtil.getDataTypeName(boolApiType) + ' to set boolean value ' + es3fUniformApiTests.apiVarValueStr(unifValue) + ' for ' + curName);
2115                 else if (gluShaderUtil.isDataTypeSampler(uniform.type))
2116                     bufferedLogToConsole('// Texture for the sampler uniform ' + curName + ' will be filled with color ' + es3fUniformApiTests.apiVarValueStr(es3fUniformApiTests.getSamplerFillValue(uniform.finalValue)));
2117             }
2119             assertMsgOptions(
2120                 valuesToAssign.length > 0,
2121                 'es3fUniformApiTests.UniformCase.prototype.assignUniforms - values quantity less than one',
2122                 false,
2123                 true
2124             );
2126             if (gluShaderUtil.isDataTypeFloatOrVec(valuesToAssign[0].type)) {
2127                 if (assignByValue) {
2128                     switch (typeSize) {
2129                         case 1: gl.uniform1f(location, valuesToAssign[0].val[0]); break;
2130                         case 2: gl.uniform2f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
2131                         case 3: gl.uniform3f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
2132                         case 4: gl.uniform4f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
2133                         default:
2134                             throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
2135                     }
2136                 } else {
2137                     buffer = new Array(valuesToAssign.length * typeSize);
2138                     for (var i = 0; i < buffer.length; i++)
2139                         buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
2141                     switch (typeSize) {
2142                         case 1: gl.uniform1fv(location, buffer); break;
2143                         case 2: gl.uniform2fv(location, buffer); break;
2144                         case 3: gl.uniform3fv(location, buffer); break;
2145                         case 4: gl.uniform4fv(location, buffer); break;
2146                         default:
2147                             throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
2148                     }
2149                 }
2150             } else if (gluShaderUtil.isDataTypeMatrix(valuesToAssign[0].type)) {
2151                 assertMsgOptions(
2152                     !assignByValue,
2153                     'es3fUniformApiTests.UniformCase.prototype.assignUniforms - assigning by value in matrix type',
2154                     false, true
2155                 );
2157                 buffer = new Array(valuesToAssign.length * typeSize);
2158                 for (var i = 0; i < buffer.length; i++)
2159                     buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
2161                 switch (uniform.type) {
2162                     case gluShaderUtil.DataType.FLOAT_MAT2: gl.uniformMatrix2fv(location, transposeGL, new Float32Array(buffer)); break;
2163                     case gluShaderUtil.DataType.FLOAT_MAT3: gl.uniformMatrix3fv(location, transposeGL, new Float32Array(buffer)); break;
2164                     case gluShaderUtil.DataType.FLOAT_MAT4: gl.uniformMatrix4fv(location, transposeGL, new Float32Array(buffer)); break;
2165                     case gluShaderUtil.DataType.FLOAT_MAT2X3: gl.uniformMatrix2x3fv(location, transposeGL, new Float32Array(buffer)); break;
2166                     case gluShaderUtil.DataType.FLOAT_MAT2X4: gl.uniformMatrix2x4fv(location, transposeGL, new Float32Array(buffer)); break;
2167                     case gluShaderUtil.DataType.FLOAT_MAT3X2: gl.uniformMatrix3x2fv(location, transposeGL, new Float32Array(buffer)); break;
2168                     case gluShaderUtil.DataType.FLOAT_MAT3X4: gl.uniformMatrix3x4fv(location, transposeGL, new Float32Array(buffer)); break;
2169                     case gluShaderUtil.DataType.FLOAT_MAT4X2: gl.uniformMatrix4x2fv(location, transposeGL, new Float32Array(buffer)); break;
2170                     case gluShaderUtil.DataType.FLOAT_MAT4X3: gl.uniformMatrix4x3fv(location, transposeGL, new Float32Array(buffer)); break;
2171                     default:
2172                         throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid uniform type');
2173                 }
2174             } else if (gluShaderUtil.isDataTypeIntOrIVec(valuesToAssign[0].type)) {
2175                 if (assignByValue) {
2176                     switch (typeSize) {
2177                         case 1: gl.uniform1i(location, valuesToAssign[0].val[0]); break;
2178                         case 2: gl.uniform2i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
2179                         case 3: gl.uniform3i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
2180                         case 4: gl.uniform4i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
2181                         default:
2182                             throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
2183                     }
2184                 } else {
2185                     buffer = new Array(valuesToAssign.length * typeSize);
2186                     for (var i = 0; i < buffer.length; i++)
2187                         buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
2189                     switch (typeSize) {
2190                         case 1: gl.uniform1iv(location, buffer); break;
2191                         case 2: gl.uniform2iv(location, buffer); break;
2192                         case 3: gl.uniform3iv(location, buffer); break;
2193                         case 4: gl.uniform4iv(location, buffer); break;
2194                         default:
2195                             throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
2196                     }
2197                 }
2198             } else if (gluShaderUtil.isDataTypeUintOrUVec(valuesToAssign[0].type)) {
2199                 if (assignByValue) {
2200                     switch (typeSize) {
2201                         case 1: gl.uniform1ui(location, valuesToAssign[0].val[0]); break;
2202                         case 2: gl.uniform2ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
2203                         case 3: gl.uniform3ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
2204                         case 4: gl.uniform4ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
2205                         default:
2206                             throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
2207                     }
2208                 } else {
2209                     buffer = new Array(valuesToAssign.length * typeSize);
2210                     for (var i = 0; i < buffer.length; i++)
2211                         buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
2213                     switch (typeSize) {
2214                         case 1: gl.uniform1uiv(location, buffer); break;
2215                         case 2: gl.uniform2uiv(location, buffer); break;
2216                         case 3: gl.uniform3uiv(location, buffer); break;
2217                         case 4: gl.uniform4uiv(location, buffer); break;
2218                         default:
2219                             throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
2220                     }
2221                 }
2222             } else if (gluShaderUtil.isDataTypeSampler(valuesToAssign[0].type)) {
2223                 if (assignByValue)
2224                    gl.uniform1i(location, uniform.finalValue.val.samplerV.unit);
2225                 else {
2226                     var unit = /** @type {Array<number>} */ (uniform.finalValue.val);
2227                    gl.uniform1iv(location, unit);
2228                 }
2229             } else
2230                 throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid uniform type');
2231         }
2232     };
2234     /**
2235      * @param {Array<es3fUniformApiTests.VarValue>} values
2236      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
2237      * @return {boolean}
2238      */
2239     es3fUniformApiTests.UniformCase.prototype.compareUniformValues = function(values, basicUniforms) {
2240         /** @type {boolean} */ var success = true;
2242         for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
2243             /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
2244             /** @type {es3fUniformApiTests.VarValue} */ var unifValue = values[unifNdx];
2246             bufferedLogToConsole('// Checking uniform ' + uniform.name);
2248             if (unifValue.type == gluShaderUtil.DataType.INVALID) // This happens when glGetUniformLocation() returned -1.
2249                 continue;
2251             if (!es3fUniformApiTests.apiVarValueEquals(unifValue, uniform.finalValue)) {
2252                 bufferedLogToConsole('// FAILURE: value obtained with glGetUniform*() for uniform ' + uniform.name + ' differs from value set with glUniform*()');
2253                 success = false;
2254             }
2255         }
2257         return success;
2258     };
2260     /** @const @type {number} */ es3fUniformApiTests.VIEWPORT_WIDTH = 128;
2261     /** @const @type {number} */ es3fUniformApiTests.VIEWPORT_HEIGHT = 128;
2263     /**
2264      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
2265      * @param {gluShaderProgram.ShaderProgram} program
2266      * @param {deRandom.Random} rnd
2267      * @return {boolean}
2268      */
2269     es3fUniformApiTests.UniformCase.prototype.renderTest = function(basicUniforms, program, rnd) {
2270         //const tcu::RenderTarget& renderTarget = m_context.getRenderTarget();
2271         /** @const */ var viewportW = Math.min(gl.canvas.width, es3fUniformApiTests.VIEWPORT_WIDTH);
2272         /** @const */ var viewportH = Math.min(gl.canvas.height, es3fUniformApiTests.VIEWPORT_HEIGHT);
2273         /** @const */ var viewportX = rnd.getInt(0, gl.canvas.width - viewportW);
2274         /** @const */ var viewportY = rnd.getInt(0, gl.canvas.height - viewportH);
2275         /** @type {tcuSurface.Surface} */ var renderedImg = new tcuSurface.Surface(viewportW, viewportH);
2277         // Assert that no two samplers of different types have the same texture unit - this is an error in GL.
2278         for (var i = 0; i < basicUniforms.length; i++) {
2279             if (gluShaderUtil.isDataTypeSampler(basicUniforms[i].type)) {
2280                 for (var j = 0; j < i; j++) {
2281                     if (gluShaderUtil.isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type)
2282                         assertMsgOptions(
2283                             basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit,
2284                             'es3fUniformApiTests.UniformCase.prototype.renderTest - sampler units have the same texture unit',
2285                             false, true
2286                         );
2287                 }
2288             }
2289         }
2291         for (var i = 0; i < basicUniforms.length; i++) {
2292             if (gluShaderUtil.isDataTypeSampler(basicUniforms[i].type) && this.m_filledTextureUnits.indexOf(basicUniforms[i].finalValue.val) == -1) {
2293                 bufferedLogToConsole('// Filling texture at unit ' + es3fUniformApiTests.apiVarValueStr(basicUniforms[i].finalValue) + ' with color ' + es3fUniformApiTests.shaderVarValueStr(basicUniforms[i].finalValue));
2294                 this.setupTexture(basicUniforms[i].finalValue);
2295             }
2296         }
2298        gl.viewport(viewportX, viewportY, viewportW, viewportH);
2300         /** @type {Float32Array} */ var position = new Float32Array([
2301             -1.0, -1.0, 0.0, 1.0,
2302             -1.0, 1.0, 0.0, 1.0,
2303             1.0, -1.0, 0.0, 1.0,
2304             1.0, 1.0, 0.0, 1.0
2305         ]);
2307         /** @type {Uint16Array} */
2308         var indices = new Uint16Array([0, 1, 2, 2, 1, 3]);
2310         /** @type {number} */ var posLoc = gl.getAttribLocation(program.getProgram(), 'a_position');
2311         gl.enableVertexAttribArray(posLoc);
2313         var gl_position_buffer = gl.createBuffer();
2314         gl.bindBuffer(gl.ARRAY_BUFFER, gl_position_buffer);
2315         gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW);
2316         gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
2318         var gl_index_buffer = gl.createBuffer();
2319         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_index_buffer);
2320         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
2322         gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
2324         renderedImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
2326         /** @type {number} */ var numFailedPixels = 0;
2327         var whitePixel = new gluDrawUtil.Pixel([255.0, 255.0, 255.0, 255.0]);
2328         for (var y = 0; y < renderedImg.getHeight(); y++) {
2329             for (var x = 0; x < renderedImg.getWidth(); x++) {
2330                 var currentPixel = new gluDrawUtil.Pixel(renderedImg.getPixel(x, y));
2331                 if (!whitePixel.equals(currentPixel))
2332                     numFailedPixels += 1;
2333             }
2334         }
2336         if (numFailedPixels > 0) {
2337             //TODO: log << TestLog::Image("RenderedImage", "Rendered image", renderedImg);
2338             bufferedLogToConsole('FAILURE: image comparison failed, got ' + numFailedPixels + ' non-white pixels');
2339             return false;
2340         } else {
2341             bufferedLogToConsole('Success: got all-white pixels (all uniforms have correct values)');
2342             return true;
2343         }
2344     };
2346     /**
2347      * @return {tcuTestCase.IterateResult}
2348      */
2349     es3fUniformApiTests.UniformCase.prototype.iterate = function() {
2350         /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ deRandom.getBaseSeed());
2351         /** @type {Array<es3fUniformApiTests.BasicUniform>} */ var basicUniforms = [];
2352         /** @type {Array<es3fUniformApiTests.BasicUniformReportRef>} */ var basicUniformReportsRef = [];
2354         /** @type {number} */ var samplerUnitCounter = 0;
2355         for (var i = 0; i < this.m_uniformCollection.getNumUniforms(); i++)
2356             samplerUnitCounter = this.generateBasicUniforms(basicUniforms, basicUniformReportsRef, this.m_uniformCollection.getUniform(i).type, this.m_uniformCollection.getUniform(i).name, true, samplerUnitCounter, rnd);
2358         /** @type {string} */ var vertexSource = this.generateVertexSource(basicUniforms);
2359         /** @type {string} */ var fragmentSource = this.generateFragmentSource(basicUniforms);
2360         /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexSource, fragmentSource));
2362         bufferedLogToConsole(program.getProgramInfo().infoLog);
2364         if (!program.isOk()) {
2365             testFailedOptions('Compile failed', false);
2366             return tcuTestCase.IterateResult.STOP;
2367         }
2369        gl.useProgram(program.getProgram());
2371         /** @type {boolean} */ var success = this.test(basicUniforms, basicUniformReportsRef, program, rnd);
2372         assertMsgOptions(success, '', true, false);
2374         return tcuTestCase.IterateResult.STOP;
2375     };
2377     /**
2378      * @enum {number}
2379      */
2380     es3fUniformApiTests.CaseType = {
2381         UNIFORM: 0, //!< Check info returned by glGetActiveUniform().
2382         INDICES_UNIFORMSIV: 1, //!< Check info returned by glGetUniformIndices() + glGetActiveUniforms(). TODO: Check 'IV' part
2383         CONSISTENCY: 2 //!< Query info with both above methods, and check consistency.
2384     };
2386     /**
2387      * es3fUniformApiTests.UniformInfoQueryCase class
2388      * @constructor
2389      * @param {string} name
2390      * @param {string} description
2391      * @param {es3fUniformApiTests.CaseShaderType} shaderType
2392      * @param {es3fUniformApiTests.UniformCollection} uniformCollection
2393      * @param {es3fUniformApiTests.CaseType} caseType
2394      * @param {es3fUniformApiTests.Feature} additionalFeatures
2395      * @extends {es3fUniformApiTests.UniformCase}
2396      */
2397     es3fUniformApiTests.UniformInfoQueryCase = function(name, description, shaderType, uniformCollection, caseType, additionalFeatures) {
2398         es3fUniformApiTests.UniformCase.call(this, name, description);
2399         this.newB(shaderType, uniformCollection, additionalFeatures);
2400         /** @type {es3fUniformApiTests.CaseType} */ this.m_caseType = caseType;
2401     };
2403     es3fUniformApiTests.UniformInfoQueryCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
2404     /** Constructor restore */
2405     es3fUniformApiTests.UniformInfoQueryCase.prototype.constructor = es3fUniformApiTests.UniformInfoQueryCase;
2407     /**
2408      * @param {es3fUniformApiTests.CaseType} caseType
2409      * @return {?string}
2410      */
2411     es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeName = function(caseType) {
2412         switch (caseType) {
2413             case es3fUniformApiTests.CaseType.UNIFORM: return 'active_uniform';
2414             case es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV: return 'indices_active_uniformsiv';
2415             case es3fUniformApiTests.CaseType.CONSISTENCY: return 'consistency';
2416             default:
2417                 throw new Error('Invalid type');
2418         }
2419     };
2421     /**
2422      * @param {es3fUniformApiTests.CaseType} caseType
2423      * @return {?string}
2424      */
2425     es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeDescription = function(caseType) {
2426        switch (caseType) {
2427            case es3fUniformApiTests.CaseType.UNIFORM: return 'Test glGetActiveUniform()';
2428            case es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV: return 'Test glGetUniformIndices() along with glGetActiveUniforms()';
2429            case es3fUniformApiTests.CaseType.CONSISTENCY: return 'Check consistency between results from glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniforms()';
2430            default:
2431                throw new Error('Invalid type');
2432        }
2433     };
2435     // \note Although this is only used in UniformApiTest::es3fUniformApiTests.init, it needs to be defined here as it's used as a template argument.
2436     /**
2437      * @constructor
2438      * @param {?string} name
2439      * @param {es3fUniformApiTests.UniformCollection} uniformCollection_
2440      */
2441     es3fUniformApiTests.UniformCollectionCase = function(name, uniformCollection_) {
2442         /** @type {string} */ this.namePrefix = name ? name + '_' : '';
2443         /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ this.uniformCollection = uniformCollection_;
2444     };
2446     /**
2447      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
2448      * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
2449      * @param {gluShaderProgram.ShaderProgram} program
2450      * @param {deRandom.Random} rnd
2451      * @return {boolean}
2452      */
2453     es3fUniformApiTests.UniformInfoQueryCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
2454         /** @type {WebGLProgram} */ var programGL = program.getProgram();
2455         /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var basicUniformReportsUniform = [];
2456         /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var basicUniformReportsUniforms = [];
2457         /** @type {boolean} */ var success;
2459         if (this.m_caseType == es3fUniformApiTests.CaseType.UNIFORM || this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
2460             success = false;
2462             //TODO:: const ScopedLogSection section(log, "InfoGetActiveUniform", "es3fUniformApiTests.Uniform information queries with glGetActiveUniform()");
2463             success = this.getActiveUniformsOneByOne(basicUniformReportsUniform, basicUniformReportsRef, programGL);
2465             if (!success) {
2466                 if (this.m_caseType == es3fUniformApiTests.CaseType.UNIFORM)
2467                     return false;
2468                 else {
2469                     assertMsgOptions(
2470                         this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY,
2471                         'es3fUniformApiTests.UniformInfoQueryCase.prototype.test - case type is not consistency',
2472                         false,
2473                         true
2474                     );
2475                     bufferedLogToConsole('// Note: this is a consistency case, so ignoring above failure(s)');
2476                 }
2477             }
2478         }
2480         if (this.m_caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV || this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
2481             success = false;
2483             //TODO: const ScopedLogSection section(log, "InfoGetActiveUniforms", "es3fUniformApiTests.Uniform information queries with glGetUniformIndices() and glGetActiveUniforms()");
2484             success = this.getActiveUniforms(basicUniformReportsUniforms, basicUniformReportsRef, programGL);
2486             if (!success) {
2487                 if (this.m_caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV)
2488                     return false;
2489                 else {
2490                     assertMsgOptions(
2491                         this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY,
2492                         'es3fUniformApiTests.UniformInfoQueryCase.prototype.test - case type is not consistency',
2493                         false,
2494                         true
2495                     );
2496                     bufferedLogToConsole('// Note: this is a consistency case, so ignoring above failure(s)');
2497                 }
2498             }
2499         }
2501         if (this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
2502             success = false;
2504             //TODO: const ScopedLogSection section(log, "CompareUniformVsUniforms", "Comparison of results from glGetActiveUniform() and glGetActiveUniforms()");
2505             success = this.uniformVsUniformsComparison(basicUniformReportsUniform, basicUniformReportsUniforms);
2507             if (!success)
2508                 return false;
2509         }
2511         return true;
2512     };
2514     /**
2515      * @enum {number}
2516      */
2517     es3fUniformApiTests.ValueToCheck = {
2518         INITIAL: 0, //!< Verify the initial values of the uniforms (i.e. check that they're zero).
2519         ASSIGNED: 1 //!< Assign values to uniforms with glUniform*(), and check those.
2520     };
2522     /**
2523      * @enum {number}
2524      */
2525     es3fUniformApiTests.CheckMethod = {
2526         GET_UNIFORM: 0, //!< Check values with glGetUniform*().
2527         RENDER: 1 //!< Check values by rendering with the value-checking shader.
2528     };
2530     /**
2531      * @enum {number}
2532      */
2533     es3fUniformApiTests.AssignMethod = {
2534         POINTER: 0,
2535         VALUE: 1
2536     };
2538     /**
2539      * es3fUniformApiTests.UniformValueCase test class
2540      * @constructor
2541      * @param {string} name
2542      * @param {string} description
2543      * @param {es3fUniformApiTests.CaseShaderType} shaderType
2544      * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
2545      * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
2546      * @param {es3fUniformApiTests.CheckMethod} checkMethod
2547      * @param {?es3fUniformApiTests.AssignMethod} assignMethod
2548      * @param {es3fUniformApiTests.Feature} additionalFeatures
2549      * @extends {es3fUniformApiTests.UniformCase}
2550      */
2551     es3fUniformApiTests.UniformValueCase = function(name, description, shaderType, uniformCollection, valueToCheck, checkMethod, assignMethod, additionalFeatures) {
2552         es3fUniformApiTests.UniformCase.call(this, name, description);
2554         additionalFeatures.UNIFORMVALUE_ZERO |= valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL;
2555         additionalFeatures.UNIFORMFUNC_VALUE |= assignMethod == es3fUniformApiTests.AssignMethod.VALUE;
2556         this.newB(shaderType, uniformCollection, additionalFeatures);
2558         this.m_valueToCheck = valueToCheck;
2559         this.m_checkMethod = checkMethod;
2561         assertMsgOptions(
2562             !(assignMethod === undefined && valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED),
2563             'es3fUniformApiTests.UniformValueCase - assign method is undefined when value to check requires it',
2564             false,
2565             true
2566         );
2567     };
2569     es3fUniformApiTests.UniformValueCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
2570     /** Constructor restore */
2571     es3fUniformApiTests.UniformValueCase.prototype.constructor = es3fUniformApiTests.UniformValueCase;
2573     /**
2574      * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
2575      * @return {?string}
2576      */
2577     es3fUniformApiTests.UniformValueCase.getValueToCheckName = function(valueToCheck) {
2578         switch (valueToCheck) {
2579             case es3fUniformApiTests.ValueToCheck.INITIAL: return 'initial';
2580             case es3fUniformApiTests.ValueToCheck.ASSIGNED: return 'assigned';
2581             default: throw new Error('es3fUniformApiTests.UniformValueCase.getValueToCheckName - Invalid value to check option');
2582         }
2583     };
2585     /**
2586      * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
2587      * @return {?string}
2588      */
2589     es3fUniformApiTests.UniformValueCase.getValueToCheckDescription = function(valueToCheck) {
2590         switch (valueToCheck) {
2591             case es3fUniformApiTests.ValueToCheck.INITIAL: return 'Check initial uniform values (zeros)';
2592             case es3fUniformApiTests.ValueToCheck.ASSIGNED: return 'Check assigned uniform values';
2593             default: throw new Error('es3fUniformApiTests.UniformValueCase.getValueToCheckDescription - Invalid value to check option');
2594         }
2595     };
2597     /**
2598      * @param {es3fUniformApiTests.CheckMethod} checkMethod
2599      * @return {?string}
2600      */
2601     es3fUniformApiTests.UniformValueCase.getCheckMethodName = function(checkMethod) {
2602         switch (checkMethod) {
2603             case es3fUniformApiTests.CheckMethod.GET_UNIFORM: return 'get_uniform';
2604             case es3fUniformApiTests.CheckMethod.RENDER: return 'render';
2605             default: throw new Error('es3fUniformApiTests.UniformValueCase.getCheckMethodName - Invalid check method');
2606         }
2607     };
2609     /**
2610      * @param {es3fUniformApiTests.CheckMethod} checkMethod
2611      * @return {?string}
2612      */
2613     es3fUniformApiTests.UniformValueCase.getCheckMethodDescription = function(checkMethod) {
2614         switch (checkMethod) {
2615             case es3fUniformApiTests.CheckMethod.GET_UNIFORM: return 'Verify values with glGetUniform*()';
2616             case es3fUniformApiTests.CheckMethod.RENDER: return 'Verify values by rendering';
2617             default: throw new Error('es3fUniformApiTests.UniformValueCase.getCheckMethodDescription - Invalid check method');
2618         }
2619     };
2621     /**
2622      * @param {es3fUniformApiTests.AssignMethod} assignMethod
2623      * @return {?string}
2624      */
2625     es3fUniformApiTests.UniformValueCase.getAssignMethodName = function(assignMethod) {
2626         switch (assignMethod) {
2627             case es3fUniformApiTests.AssignMethod.POINTER: return 'by_pointer';
2628             case es3fUniformApiTests.AssignMethod.VALUE: return 'by_value';
2629             default: throw new Error('es3fUniformApiTests.UniformValueCase.getAssignMethodName - Invalid assign method');
2630         }
2631     };
2633     /**
2634      * @param {es3fUniformApiTests.AssignMethod} assignMethod
2635      * @return {?string}
2636      */
2637     es3fUniformApiTests.UniformValueCase.getAssignMethodDescription = function(assignMethod) {
2638         switch (assignMethod) {
2639             case es3fUniformApiTests.AssignMethod.POINTER: return 'Assign values by-pointer';
2640             case es3fUniformApiTests.AssignMethod.VALUE: return 'Assign values by-value';
2641             default: throw new Error('es3fUniformApiTests.UniformValueCase.getAssignMethodDescription - Invalid assign method');
2642         }
2643     };
2645     /**
2646      * es3fUniformApiTests.UniformValueCase test function
2647      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
2648      * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
2649      * @param {gluShaderProgram.ShaderProgram} program
2650      * @param {deRandom.Random} rnd
2651      * @return {boolean}
2652      */
2653     es3fUniformApiTests.UniformValueCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
2654         /** @type {WebGLProgram} */ var programGL = program.getProgram();
2656         if (this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED) {
2657             //TODO: const ScopedLogSection section(log, "UniformAssign", "es3fUniformApiTests.Uniform value assignments");
2658             this.assignUniforms(basicUniforms, programGL, rnd);
2659         } else
2660             assertMsgOptions(
2661                 this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL,
2662                 'es3fUniformApiTests.UniformValueCase.prototype.test - value to check not initial',
2663                 false, true
2664             );
2666         /** @type {boolean}*/ var success;
2668         if (this.m_checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM) {
2669             /** @type {Array<es3fUniformApiTests.VarValue>} */ var values = [];
2671             //TODO: const ScopedLogSection section(log, "GetUniforms", "es3fUniformApiTests.Uniform value query");
2672             success = this.getUniforms(values, basicUniforms, program.getProgram());
2674             if (!success)
2675                 return false;
2677             if (this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED) {
2678                 //TODO: const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values");
2679                 success = this.compareUniformValues(values, basicUniforms);
2681                 if (!success)
2682                     return false;
2683             } else {
2684                 assertMsgOptions(
2685                     this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL,
2686                     'es3fUniformApiTests.UniformValueCase.prototype.test - value to check not initial',
2687                     false, true
2688                 );
2690                 //TODO: const ScopedLogSection section(log, "ValueCheck", "Verify that the uniforms have correct initial values (zeros)");
2691                 success = this.checkUniformDefaultValues(values, basicUniforms);
2693                 if (!success)
2694                     return false;
2695             }
2696         } else {
2697             assertMsgOptions(
2698                 this.m_checkMethod == es3fUniformApiTests.CheckMethod.RENDER,
2699                 'es3fUniformApiTests.UniformValueCase.prototype.test - check method different than RENDER',
2700                 false, true
2701             );
2703             //TODO: const ScopedLogSection section(log, "RenderTest", "Render test");
2704             success = this.renderTest(basicUniforms, program, rnd);
2706             if (!success)
2707                 return false;
2708         }
2710         return true;
2711     };
2713     /**
2714      * es3fUniformApiTests.RandomUniformCase test class
2715      * @constructor
2716      * @param {string} name
2717      * @param {string} description
2718      * @param {number} seed
2719      * @extends {es3fUniformApiTests.UniformCase}
2720      */
2721     es3fUniformApiTests.RandomUniformCase = function(name, description, seed) {
2722         es3fUniformApiTests.UniformCase.call(this, name, description);
2723         this.newC(seed ^ deRandom.getBaseSeed());
2724     };
2726     es3fUniformApiTests.RandomUniformCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
2727     /** Constructor restore */
2728     es3fUniformApiTests.RandomUniformCase.prototype.constructor = es3fUniformApiTests.RandomUniformCase;
2730     /**
2731      * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
2732      * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
2733      * @param {gluShaderProgram.ShaderProgram} program
2734      * @param {deRandom.Random} rnd
2735      * @return {boolean}
2736      */
2737     es3fUniformApiTests.RandomUniformCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
2738         // \note Different sampler types may not be bound to same unit when rendering.
2739         /** @type {boolean}*/ var renderingPossible = !this.m_features.UNIFORMVALUE_ZERO || !this.m_uniformCollection.containsSeveralSamplerTypes();
2741         /** @type {boolean} */ var performGetActiveUniforms = rnd.getBool();
2742         /** @type {boolean} */ var performGetActiveUniformsiv = rnd.getBool();
2743         /** @type {boolean} */ var performUniformVsUniformsivComparison = performGetActiveUniforms && performGetActiveUniformsiv && rnd.getBool();
2744         /** @type {boolean} */ var performGetUniforms = rnd.getBool();
2745         /** @type {boolean} */ var performCheckUniformDefaultValues = performGetUniforms && rnd.getBool();
2746         /** @type {boolean} */ var performAssignUniforms = rnd.getBool();
2747         /** @type {boolean} */ var performCompareUniformValues = performGetUniforms && performAssignUniforms && rnd.getBool();
2748         /** @type {boolean} */ var performRenderTest = renderingPossible && performAssignUniforms && rnd.getBool();
2749         /** @type {WebGLProgram} */ var programGL = program.getProgram();
2751         if (!(performGetActiveUniforms || performGetActiveUniformsiv || performUniformVsUniformsivComparison || performGetUniforms || performCheckUniformDefaultValues || performAssignUniforms || performCompareUniformValues || performRenderTest))
2752             performGetActiveUniforms = true; // Do something at least.
2754         var PERFORM_AND_CHECK = function(CALL, SECTION_NAME, SECTION_DESCRIPTION) {
2755             //TODO: const ScopedLogSection section(log, (SECTION_NAME), (SECTION_DESCRIPTION));
2756             /** @type {boolean} */ var success = CALL();
2757             if (!success)
2758                 return false;
2759         };
2761         /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var reportsUniform = [];
2762         /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var reportsUniformsiv = [];
2764         var current = this; //To use "this" in anonymous function.
2766         if (performGetActiveUniforms)
2767             PERFORM_AND_CHECK(function() {current.getActiveUniformsOneByOne(reportsUniform, basicUniformReportsRef, programGL);}, 'InfoGetActiveUniform', 'es3fUniformApiTests.Uniform information queries with glGetActiveUniform()');
2769         if (performGetActiveUniformsiv)
2770             PERFORM_AND_CHECK(function() {current.getActiveUniforms(reportsUniformsiv, basicUniformReportsRef, programGL);}, 'InfoGetActiveUniformsiv', 'es3fUniformApiTests.Uniform information queries with glGetIndices() and glGetActiveUniformsiv()');
2772         if (performUniformVsUniformsivComparison)
2773             PERFORM_AND_CHECK(function() {current.uniformVsUniformsComparison(reportsUniform, reportsUniformsiv);}, 'CompareUniformVsUniformsiv', 'Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()');
2775         /** @type {Array<es3fUniformApiTests.VarValue>} */ var uniformDefaultValues = [];
2777         if (performGetUniforms)
2778             PERFORM_AND_CHECK(function() {current.getUniforms(uniformDefaultValues, basicUniforms, programGL);}, 'GetUniformDefaults', 'es3fUniformApiTests.Uniform default value query');
2780         if (performCheckUniformDefaultValues)
2781             PERFORM_AND_CHECK(function() {current.checkUniformDefaultValues(uniformDefaultValues, basicUniforms);}, 'DefaultValueCheck', 'Verify that the uniforms have correct initial values (zeros)');
2783         /** @type {Array<es3fUniformApiTests.VarValue>} */ var uniformValues = [];
2785         if (performAssignUniforms) {
2786             //TODO: const ScopedLogSection section(log, "UniformAssign", "es3fUniformApiTests.Uniform value assignments");
2787             this.assignUniforms(basicUniforms, programGL, rnd);
2788         }
2790         if (performCompareUniformValues) {
2791             PERFORM_AND_CHECK(function() {current.getUniforms(uniformValues, basicUniforms, programGL);}, 'GetUniforms', 'es3fUniformApiTests.Uniform value query');
2792             PERFORM_AND_CHECK(function() {current.compareUniformValues(uniformValues, basicUniforms);}, 'ValueCheck', 'Verify that the reported values match the assigned values');
2793         }
2795         if (performRenderTest)
2796             PERFORM_AND_CHECK(function() {current.renderTest(basicUniforms, program, rnd);}, 'RenderTest', 'Render test');
2798         return true;
2799     };
2801     /**
2802      * Initializes the tests to be performed.
2803      */
2804     es3fUniformApiTests.init = function() {
2805         var state = tcuTestCase.runner;
2806         var testGroup = state.testCases;
2808         // Generate sets of UniformCollections that are used by several cases.
2809         /**
2810          * @enum
2811          */
2812         var UniformCollections = {
2813             BASIC: 0,
2814             BASIC_ARRAY: 1,
2815             BASIC_STRUCT: 2,
2816             STRUCT_IN_ARRAY: 3,
2817             ARRAY_IN_STRUCT: 4,
2818             NESTED_STRUCTS_ARRAYS: 5,
2819             MULTIPLE_BASIC: 6,
2820             MULTIPLE_BASIC_ARRAY: 7,
2821             MULTIPLE_NESTED_STRUCTS_ARRAYS: 8
2822         };
2824         /**
2825          * @constructor
2826          */
2827         var UniformCollectionGroup = function() {
2828             /** @type {string} */ this.name = '';
2829             /** @type {Array<es3fUniformApiTests.UniformCollectionCase>} */ this.cases = [];
2830         };
2832         /** @type {Array<UniformCollectionGroup>} */ var defaultUniformCollections = new Array(Object.keys(UniformCollections).length);
2834         /** @type {string} */ var name;
2836         //Initialize
2837         for (var i = 0; i < defaultUniformCollections.length; i++) defaultUniformCollections[i] = new UniformCollectionGroup();
2839         defaultUniformCollections[UniformCollections.BASIC].name = 'basic';
2840         defaultUniformCollections[UniformCollections.BASIC_ARRAY].name = 'basic_array';
2841         defaultUniformCollections[UniformCollections.BASIC_STRUCT].name = 'basic_struct';
2842         defaultUniformCollections[UniformCollections.STRUCT_IN_ARRAY].name = 'struct_in_array';
2843         defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT].name = 'array_in_struct';
2844         defaultUniformCollections[UniformCollections.NESTED_STRUCTS_ARRAYS].name = 'nested_structs_arrays';
2845         defaultUniformCollections[UniformCollections.MULTIPLE_BASIC].name = 'multiple_basic';
2846         defaultUniformCollections[UniformCollections.MULTIPLE_BASIC_ARRAY].name = 'multiple_basic_array';
2847         defaultUniformCollections[UniformCollections.MULTIPLE_NESTED_STRUCTS_ARRAYS].name = 'multiple_nested_structs_arrays';
2849         for (var dataTypeNdx = 0; dataTypeNdx < es3fUniformApiTests.s_testDataTypes.length; dataTypeNdx++) {
2850             /** @type {gluShaderUtil.DataType} */ var dataType = es3fUniformApiTests.s_testDataTypes[dataTypeNdx];
2851             /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(dataType);
2853             defaultUniformCollections[UniformCollections.BASIC].cases.push(new es3fUniformApiTests.UniformCollectionCase(typeName, es3fUniformApiTests.UniformCollection.basic(dataType)));
2855             if (gluShaderUtil.isDataTypeScalar(dataType) ||
2856                 (gluShaderUtil.isDataTypeVector(dataType) && gluShaderUtil.getDataTypeScalarSize(dataType) == 4) ||
2857                 dataType == gluShaderUtil.DataType.FLOAT_MAT4 ||
2858                 dataType == gluShaderUtil.DataType.SAMPLER_2D)
2859                 defaultUniformCollections[UniformCollections.BASIC_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(typeName, es3fUniformApiTests.UniformCollection.basicArray(dataType)));
2861             if (gluShaderUtil.isDataTypeScalar(dataType) ||
2862                 dataType == gluShaderUtil.DataType.FLOAT_MAT4 ||
2863                 dataType == gluShaderUtil.DataType.SAMPLER_2D) {
2864                 /** @type {gluShaderUtil.DataType} */ var secondDataType;
2865                 if (gluShaderUtil.isDataTypeScalar(dataType))
2866                     secondDataType = gluShaderUtil.getDataTypeVector(dataType, 4);
2867                 else if (dataType == gluShaderUtil.DataType.FLOAT_MAT4)
2868                     secondDataType = gluShaderUtil.DataType.FLOAT_MAT2;
2869                 else if (dataType == gluShaderUtil.DataType.SAMPLER_2D)
2870                     secondDataType = gluShaderUtil.DataType.SAMPLER_CUBE;
2872                 assertMsgOptions(
2873                     secondDataType !== undefined,
2874                     'es3fUniformApiTests.init - second data type undefined',
2875                     false, true
2876                 );
2878                 /** @type {string} */ var secondTypeName = gluShaderUtil.getDataTypeName(secondDataType);
2879                 name = typeName + '_' + secondTypeName;
2881                 defaultUniformCollections[UniformCollections.BASIC_STRUCT].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.basicStruct(dataType, secondDataType, false)));
2882                 defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.basicStruct(dataType, secondDataType, true)));
2883                 defaultUniformCollections[UniformCollections.STRUCT_IN_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.structInArray(dataType, secondDataType, false)));
2884                 defaultUniformCollections[UniformCollections.NESTED_STRUCTS_ARRAYS].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.nestedArraysStructs(dataType, secondDataType)));
2885             }
2886         }
2887         defaultUniformCollections[UniformCollections.MULTIPLE_BASIC].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleBasic()));
2888         defaultUniformCollections[UniformCollections.MULTIPLE_BASIC_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleBasicArray()));
2889         defaultUniformCollections[UniformCollections.MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs()));
2891         // Info-query cases (check info returned by e.g. glGetActiveUniforms()).
2893         // info_query
2894         /** @type {tcuTestCase.DeqpTest} */
2895         var infoQueryGroup = tcuTestCase.newTest('info_query', 'Test uniform info querying functions');
2896         testGroup.addChild(infoQueryGroup);
2898         /** @type {UniformCollectionGroup} */ var collectionGroup;
2899         /** @type {es3fUniformApiTests.UniformCollectionCase} */ var collectionCase;
2900         /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ var uniformCollection;
2901         /** @type {es3fUniformApiTests.Feature} */ var features;
2902         /** @type {tcuTestCase.DeqpTest} */ var collectionTestGroup;
2903         /** @type {string} */ var collName;
2904         /** @type {es3fUniformApiTests.CheckMethod} */ var checkMethod;
2905         /** @type {tcuTestCase.DeqpTest} */ var checkMethodGroup;
2906         /** @type {string} */ var collectionGroupName;
2907         /** @type {boolean} */ var containsBooleans;
2908         /** @type {boolean} */ var varyBoolApiType;
2909         /** @type {number} */ var numBoolVariations;
2910         /** @type {es3fUniformApiTests.Feature} */ var booleanTypeFeat;
2911         /** @type {string} */ var booleanTypeName;
2912         /** @type {tcuTestCase.DeqpTest} */ var unusedUniformsGroup;
2914         /** @type {Array<string>} */ var shaderTypes = Object.keys(es3fUniformApiTests.CaseShaderType);
2916         for (var caseTypeI in es3fUniformApiTests.CaseType) {
2917             /** @type {es3fUniformApiTests.CaseType} */ var caseType = es3fUniformApiTests.CaseType[caseTypeI];
2918             /** @type {tcuTestCase.DeqpTest} */
2919             var caseTypeGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeName(caseType), es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeDescription(caseType));
2920             infoQueryGroup.addChild(caseTypeGroup);
2922             for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
2923                 var numArrayFirstElemNameCases = caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV && collectionGroupNdx == UniformCollections.BASIC_ARRAY ? 2 : 1;
2925                 for (var referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) {
2926                     collectionGroup = defaultUniformCollections[collectionGroupNdx];
2927                     collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? '' : '_first_elem_without_brackets');
2928                     collectionTestGroup = tcuTestCase.newTest(collectionGroupName, '');
2929                     caseTypeGroup.addChild(collectionTestGroup);
2931                     for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
2932                         collectionCase = collectionGroup.cases[collectionNdx];
2934                         for (var i = 0; i < shaderTypes.length; i++) {
2935                             name = collectionCase.namePrefix + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
2936                             uniformCollection = collectionCase.uniformCollection;
2938                             features = new es3fUniformApiTests.Feature();
2939                             features.ARRAY_FIRST_ELEM_NAME_NO_INDEX = referToFirstArrayElemWithoutIndexI != 0;
2941                             collectionTestGroup.addChild(new es3fUniformApiTests.UniformInfoQueryCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection, caseType, features));
2942                         }
2943                     }
2944                 }
2945             }
2947             // Info-querying cases when unused uniforms are present.
2949             unusedUniformsGroup = tcuTestCase.newTest('unused_uniforms', 'Test with unused uniforms');
2950             caseTypeGroup.addChild(unusedUniformsGroup);
2952             collectionGroup = defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT];
2954             for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
2955                 collectionCase = collectionGroup.cases[collectionNdx];
2956                 collName = collectionCase.namePrefix;
2957                 uniformCollection = collectionCase.uniformCollection;
2959                 for (var i = 0; i < shaderTypes.length; i++) {
2960                     name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
2962                     features = new es3fUniformApiTests.Feature();
2963                     features.UNIFORMUSAGE_EVERY_OTHER = true;
2964                     features.ARRAYUSAGE_ONLY_MIDDLE_INDEX = true;
2966                     unusedUniformsGroup.addChild(new es3fUniformApiTests.UniformInfoQueryCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection, caseType, features));
2967                 }
2968             }
2969         }
2971         // Cases testing uniform values.
2973         // Cases checking uniforms' initial values (all must be zeros), with glGetUniform*() or by rendering.
2975         /** @type {tcuTestCase.DeqpTest} */ var initialValuesGroup = tcuTestCase.newTest(
2976             'value.' + es3fUniformApiTests.UniformValueCase.getValueToCheckName(es3fUniformApiTests.ValueToCheck.INITIAL),
2977             es3fUniformApiTests.UniformValueCase.getValueToCheckDescription(es3fUniformApiTests.ValueToCheck.INITIAL));
2978         testGroup.addChild(initialValuesGroup);
2980         for (var checkMethodI in es3fUniformApiTests.CheckMethod) {
2981             checkMethod = es3fUniformApiTests.CheckMethod[checkMethodI];
2982             checkMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getCheckMethodName(checkMethod), es3fUniformApiTests.UniformValueCase.getCheckMethodDescription(checkMethod));
2983             initialValuesGroup.addChild(checkMethodGroup);
2985             for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
2986                 collectionGroup = defaultUniformCollections[collectionGroupNdx];
2987                 collectionTestGroup = tcuTestCase.newTest(collectionGroup.name, '');
2988                 checkMethodGroup.addChild(collectionTestGroup);
2990                 for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
2991                     collectionCase = collectionGroup.cases[collectionNdx];
2992                     collName = collectionCase.namePrefix;
2993                     uniformCollection = collectionCase.uniformCollection;
2994                     containsBooleans = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeBoolOrBVec);
2995                     varyBoolApiType = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && containsBooleans &&
2996                                                                 (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
2997                     numBoolVariations = varyBoolApiType ? 3 : 1;
2999                     if (checkMethod == es3fUniformApiTests.CheckMethod.RENDER && uniformCollection.containsSeveralSamplerTypes())
3000                         continue; // \note Samplers' initial API values (i.e. their texture units) are 0, and no two samplers of different types shall have same unit when rendering.
3002                     for (var booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) {
3003                         booleanTypeFeat = new es3fUniformApiTests.Feature();
3004                         booleanTypeFeat.BOOLEANAPITYPE_INT = booleanTypeI == 1;
3005                         booleanTypeFeat.BOOLEANAPITYPE_UINT = booleanTypeI == 2;
3007                         booleanTypeName = booleanTypeI == 1 ? 'int' :
3008                                                             booleanTypeI == 2 ? 'uint' :
3009                                                             'float';
3010                         /** @type {string} */ var nameWithApiType = varyBoolApiType ? collName + 'api_' + booleanTypeName + '_' : collName;
3012                         for (var i = 0; i < shaderTypes.length; i++) {
3013                             name = nameWithApiType + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
3014                             collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
3015                                                                                 es3fUniformApiTests.ValueToCheck.INITIAL, checkMethod, null, booleanTypeFeat));
3016                         }
3017                     }
3018                 }
3019             }
3020         }
3022         // Cases that first assign values to each uniform, then check the values with glGetUniform*() or by rendering.
3024         /** @type {tcuTestCase.DeqpTest} */ var assignedValuesGroup = tcuTestCase.newTest(
3025             'value.' + es3fUniformApiTests.UniformValueCase.getValueToCheckName(es3fUniformApiTests.ValueToCheck.ASSIGNED),
3026             es3fUniformApiTests.UniformValueCase.getValueToCheckDescription(es3fUniformApiTests.ValueToCheck.ASSIGNED));
3027         testGroup.addChild(assignedValuesGroup);
3029         for (var assignMethodI in es3fUniformApiTests.AssignMethod) {
3030             /** @type {es3fUniformApiTests.AssignMethod} */ var assignMethod = es3fUniformApiTests.AssignMethod[assignMethodI];
3031             /** @type {tcuTestCase.DeqpTest} */ var assignMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getAssignMethodName(assignMethod), es3fUniformApiTests.UniformValueCase.getAssignMethodDescription(assignMethod));
3032             assignedValuesGroup.addChild(assignMethodGroup);
3034             for (var checkMethodI in es3fUniformApiTests.CheckMethod) {
3035                 checkMethod = es3fUniformApiTests.CheckMethod[checkMethodI];
3036                 checkMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getCheckMethodName(checkMethod), es3fUniformApiTests.UniformValueCase.getCheckMethodDescription(checkMethod));
3037                 assignMethodGroup.addChild(checkMethodGroup);
3039                 for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
3040                     /** @type {number} */ var numArrayFirstElemNameCases = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && collectionGroupNdx == UniformCollections.BASIC_ARRAY ? 2 : 1;
3042                     for (var referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) {
3043                         collectionGroup = defaultUniformCollections[collectionGroupNdx];
3044                         collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? '' : '_first_elem_without_brackets');
3045                         collectionTestGroup = tcuTestCase.newTest(collectionGroupName, '');
3046                         checkMethodGroup.addChild(collectionTestGroup);
3048                         for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
3049                             collectionCase = collectionGroup.cases[collectionNdx];
3050                             collName = collectionCase.namePrefix;
3051                             uniformCollection = collectionCase.uniformCollection;
3052                             containsBooleans = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeBoolOrBVec);
3053                             varyBoolApiType = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && containsBooleans &&
3054                                                                             (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
3055                             numBoolVariations = varyBoolApiType ? 3 : 1;
3056                             /** @type {boolean} */ var containsMatrices = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeMatrix);
3057                             /** @type {boolean} */ var varyMatrixMode = containsMatrices &&
3058                                                                             (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
3059                             /** @type {number} */ var numMatVariations = varyMatrixMode ? 2 : 1;
3061                             if (containsMatrices && assignMethod != es3fUniformApiTests.AssignMethod.POINTER)
3062                                 continue;
3064                             for (var booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) {
3065                                 booleanTypeFeat = new es3fUniformApiTests.Feature();
3066                                 booleanTypeFeat.BOOLEANAPITYPE_INT = booleanTypeI == 1;
3067                                 booleanTypeFeat.BOOLEANAPITYPE_UINT = booleanTypeI == 2;
3069                                 booleanTypeName = booleanTypeI == 1 ? 'int' :
3070                                                                         booleanTypeI == 2 ? 'uint' :
3071                                                                         'float';
3072                                 /** @type {string} */ var nameWithBoolType = varyBoolApiType ? collName + 'api_' + booleanTypeName + '_' : collName;
3074                                 for (var matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++) {
3075                                     /** @type {string} */ var nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? 'row_major_' : '');
3077                                     for (var i = 0; i < shaderTypes.length; i++) {
3078                                         name = nameWithMatrixType + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
3080                                         booleanTypeFeat.ARRAY_FIRST_ELEM_NAME_NO_INDEX = referToFirstArrayElemWithoutIndexI != 0;
3081                                         booleanTypeFeat.MATRIXMODE_ROWMAJOR = matrixTypeI == 1;
3083                                         collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
3084                                                                                             es3fUniformApiTests.ValueToCheck.ASSIGNED, checkMethod, assignMethod, booleanTypeFeat));
3085                                     }
3086                                 }
3087                             }
3088                         }
3089                     }
3090                 }
3091             }
3092         }
3094         // Cases assign multiple basic-array elements with one glUniform*v() (i.e. the count parameter is bigger than 1).
3096         /** @type {es3fUniformApiTests.Feature} */ var arrayAssignFullMode = new es3fUniformApiTests.Feature();
3097         arrayAssignFullMode.ARRAYASSIGN_FULL = true;
3099         /** @type {es3fUniformApiTests.Feature} */ var arrayAssignBlocksOfTwo = new es3fUniformApiTests.Feature();
3100         arrayAssignFullMode.ARRAYASSIGN_BLOCKS_OF_TWO = true;
3102         var arrayAssignGroups =
3103         [{arrayAssignMode: arrayAssignFullMode, name: 'basic_array_assign_full', description: 'Assign entire basic-type arrays per glUniform*v() call'}, {arrayAssignMode: arrayAssignBlocksOfTwo, name: 'basic_array_assign_partial', description: 'Assign two elements of a basic-type array per glUniform*v() call'}
3104         ];
3106         for (var arrayAssignGroupNdx = 0; arrayAssignGroupNdx < arrayAssignGroups.length; arrayAssignGroupNdx++) {
3107             /** @type {es3fUniformApiTests.Feature} */ var arrayAssignMode = arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode;
3108             /** @type {string} */ var groupName = arrayAssignGroups[arrayAssignGroupNdx].name;
3109             /** @type {string} */ var groupDesc = arrayAssignGroups[arrayAssignGroupNdx].description;
3111             /** @type {tcuTestCase.DeqpTest} */ var curArrayAssignGroup = tcuTestCase.newTest(groupName, groupDesc);
3112             assignedValuesGroup.addChild(curArrayAssignGroup);
3114             /** @type {Array<number>} */ var basicArrayCollectionGroups = [UniformCollections.BASIC_ARRAY, UniformCollections.ARRAY_IN_STRUCT, UniformCollections.MULTIPLE_BASIC_ARRAY];
3116             for (var collectionGroupNdx = 0; collectionGroupNdx < basicArrayCollectionGroups.length; collectionGroupNdx++) {
3117                 collectionGroup = defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]];
3118                 collectionTestGroup = tcuTestCase.newTest(collectionGroup.name, '');
3119                 curArrayAssignGroup.addChild(collectionTestGroup);
3121                 for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
3122                     collectionCase = collectionGroup.cases[collectionNdx];
3123                     collName = collectionCase.namePrefix;
3124                     uniformCollection = collectionCase.uniformCollection;
3126                     for (var i = 0; i < shaderTypes.length; i++) {
3127                         name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
3128                         collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
3129                                                                             es3fUniformApiTests.ValueToCheck.ASSIGNED, es3fUniformApiTests.CheckMethod.GET_UNIFORM, es3fUniformApiTests.AssignMethod.POINTER,
3130                                                                             arrayAssignMode));
3131                     }
3132                 }
3133             }
3134         }
3136         // Value checking cases when unused uniforms are present.
3138         unusedUniformsGroup = tcuTestCase.newTest('unused_uniforms', 'Test with unused uniforms');
3139         assignedValuesGroup.addChild(unusedUniformsGroup);
3141         collectionGroup = defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT];
3143         for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
3144             collectionCase = collectionGroup.cases[collectionNdx];
3145             collName = collectionCase.namePrefix;
3146             uniformCollection = collectionCase.uniformCollection;
3148             for (var i = 0; i < shaderTypes.length; i++) {
3149                 name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
3151                 features = new es3fUniformApiTests.Feature();
3152                 features.ARRAYUSAGE_ONLY_MIDDLE_INDEX = true;
3153                 features.UNIFORMUSAGE_EVERY_OTHER = true;
3155                 unusedUniformsGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
3156                                                                     es3fUniformApiTests.ValueToCheck.ASSIGNED, es3fUniformApiTests.CheckMethod.GET_UNIFORM, es3fUniformApiTests.AssignMethod.POINTER,
3157                                                                     features));
3158             }
3159         }
3161         // Random cases.
3163         /** @type {number} */ var numRandomCases = 100;
3164         /** @type {tcuTestCase.DeqpTest} */ var randomGroup = tcuTestCase.newTest('random', 'Random cases');
3165         testGroup.addChild(randomGroup);
3167         for (var ndx = 0; ndx < numRandomCases; ndx++)
3168             randomGroup.addChild(new es3fUniformApiTests.RandomUniformCase('' + ndx, '', ndx));
3169     };
3171     /**
3172      * Create and execute the test cases
3173      * @param {WebGL2RenderingContext} context
3174      */
3175     es3fUniformApiTests.run = function(context, range) {
3176         gl = context;
3177         //Set up Test Root parameters
3178         var testName = 'uniform_api';
3179         var testDescription = 'es3fUniformApiTests.Uniform API Tests';
3180         var state = tcuTestCase.runner;
3182         state.testName = testName;
3183         state.testCases = tcuTestCase.newTest(testName, testDescription, null);
3185         //Set up name and description of this test series.
3186         setCurrentTestName(testName);
3187         description(testDescription);
3189         try {
3190             //Create test cases
3191             es3fUniformApiTests.init();
3192             if (range)
3193                 state.setRange(range);
3194             //Run test cases
3195             tcuTestCase.runTestCases();
3196         }
3197         catch (err) {
3198             testFailedOptions('Failed to es3fUniformApiTests.run tests', false);
3199             tcuTestCase.runner.terminate();
3200         }
3201     };