Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / functional / gles3 / es3fShaderIndexingTests.js
blobc08db90758291b21fb5b23a22325184c882d2c64
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.es3fShaderIndexingTests');
23 goog.require('framework.common.tcuImageCompare');
24 goog.require('framework.common.tcuStringTemplate');
25 goog.require('framework.common.tcuTestCase');
26 goog.require('framework.delibs.debase.deMath');
27 goog.require('framework.opengl.gluShaderUtil');
28 goog.require('framework.opengl.gluShaderProgram');
29 goog.require('framework.opengl.gluTexture');
30 goog.require('modules.shared.glsShaderRenderCase');
32 goog.scope(function() {
33     /** @type {?WebGL2RenderingContext} */ var gl;
34     var es3fShaderIndexingTests = functional.gles3.es3fShaderIndexingTests;
35     var deMath = framework.delibs.debase.deMath;
36     var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
37     var gluShaderUtil = framework.opengl.gluShaderUtil;
38     var gluTexture = framework.opengl.gluTexture;
39     var gluShaderProgram = framework.opengl.gluShaderProgram;
40     var tcuTestCase = framework.common.tcuTestCase;
41     var tcuStringTemplate = framework.common.tcuStringTemplate;
42     /**
43      * @enum {number}
44      */
45     es3fShaderIndexingTests.IndexAccessType = {
46         STATIC: 0,
47         DYNAMIC: 1,
48         STATIC_LOOP: 2,
49         DYNAMIC_LOOP: 3
50     };
52     /**
53      * @param {es3fShaderIndexingTests.IndexAccessType} accessType
54      * @return {string}
55      */
56     es3fShaderIndexingTests.getIndexAccessTypeName = function(accessType) {
57         /** @type {Array<string>} */ var s_names = [
58             'static',
59             'dynamic',
60             'static_loop',
61             'dynamic_loop'
62         ];
63         return s_names[accessType];
64     };
66     /**
67      * @enum {number}
68      */
69     es3fShaderIndexingTests.VectorAccessType = {
70         DIRECT: 0,
71         COMPONENT: 1,
72         SUBSCRIPT_STATIC: 2,
73         SUBSCRIPT_DYNAMIC: 3,
74         SUBSCRIPT_STATIC_LOOP: 4,
75         SUBSCRIPT_DYNAMIC_LOOP: 5
76     };
78     /**
79      * @param {es3fShaderIndexingTests.VectorAccessType} accessType
80      * @return {string}
81      */
82     es3fShaderIndexingTests.getVectorAccessTypeName = function(accessType) {
83         /** @type {Array<string>} */ var s_names = [
84             'direct',
85             'component',
86             'static_subscript',
87             'dynamic_subscript',
88             'static_loop_subscript',
89             'dynamic_loop_subscript'
90         ];
91         assertMsgOptions(deMath.deInBounds32(accessType, 0, s_names.length), 'Index out of bounds', false, true);
92         return s_names[accessType];
93     };
95     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
96     es3fShaderIndexingTests.evalArrayCoordsFloat = function(c) {
97         c.color[0] = 1.875 * c.coords[0];
98     };
100     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
101     es3fShaderIndexingTests.evalArrayCoordsVec2 = function(c) {
102         var swizzled = deMath.swizzle(c.coords, [0, 1]);
103         c.color[0] = 1.875 * swizzled[0];
104         c.color[1] = 1.875 * swizzled[1];
105     };
107     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
108     es3fShaderIndexingTests.evalArrayCoordsVec3 = function(c) {
109         var swizzled = deMath.swizzle(c.coords, [0, 1, 2]);
110         c.color[0] = 1.875 * swizzled[0];
111         c.color[1] = 1.875 * swizzled[1];
112         c.color[2] = 1.875 * swizzled[2];
113     };
115     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
116     es3fShaderIndexingTests.evalArrayCoordsVec4 = function(c) {
117         c.color = deMath.scale(c.coords, 1.875);
118     };
120     /**
121      * @param {gluShaderUtil.DataType} dataType
122      * @return {function(glsShaderRenderCase.ShaderEvalContext)}
123      */
124     es3fShaderIndexingTests.getArrayCoordsEvalFunc = function(dataType) {
125         if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayCoordsFloat;
126         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayCoordsVec2;
127         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayCoordsVec3;
128         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayCoordsVec4;
129         else throw new Error('Invalid data type.');
130     };
133     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
134     es3fShaderIndexingTests.evalArrayUniformFloat = function(c) {
135         c.color[0] = 1.875 * c.constCoords[0];
136     };
138     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
139     es3fShaderIndexingTests.evalArrayUniformVec2 = function(c) {
140         var swizzled = deMath.swizzle(c.constCoords, [0, 1]);
141         c.color[0] = 1.875 * swizzled[0];
142         c.color[1] = 1.875 * swizzled[1];
143     };
145     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
146     es3fShaderIndexingTests.evalArrayUniformVec3 = function(c) {
147         var swizzled = deMath.swizzle(c.constCoords, [0, 1, 2]);
148         c.color[0] = 1.875 * swizzled[0];
149         c.color[1] = 1.875 * swizzled[1];
150         c.color[2] = 1.875 * swizzled[2];
151     };
153     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
154     es3fShaderIndexingTests.evalArrayUniformVec4 = function(c) {
155         c.color = deMath.scale(c.constCoords, 1.875);
156     };
158     /**
159      * @param {gluShaderUtil.DataType} dataType
160      * @return {function(glsShaderRenderCase.ShaderEvalContext)}
161      */
162     es3fShaderIndexingTests.getArrayUniformEvalFunc = function(dataType) {
163         if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayUniformFloat;
164         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayUniformVec2;
165         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayUniformVec3;
166         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayUniformVec4;
167         else throw new Error('Invalid data type.');
168     };
170     /**
171      * @constructor
172      * @extends {glsShaderRenderCase.ShaderRenderCase}
173      * @param {string} name
174      * @param {string} description
175      * @param {boolean} isVertexCase
176      * @param {gluShaderUtil.DataType} varType
177      * @param {function(glsShaderRenderCase.ShaderEvalContext)} evalFunc
178      * @param {string} vertShaderSource
179      * @param {string} fragShaderSource
180      */
181     es3fShaderIndexingTests.ShaderIndexingCase = function(name, description, isVertexCase, varType, evalFunc, vertShaderSource, fragShaderSource) {
182         glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
183         /** @type {gluShaderUtil.DataType} */ this.m_varType = varType;
184         /** @type {string} */ this.m_vertShaderSource    = vertShaderSource;
185         /** @type {string} */ this.m_fragShaderSource    = fragShaderSource;
186     };
188     es3fShaderIndexingTests.ShaderIndexingCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
189     es3fShaderIndexingTests.ShaderIndexingCase.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingCase;
191     /**
192      * @param {?WebGLProgram} programID
193      * @param {Array<number>} constCoords
194      */
195     es3fShaderIndexingTests.ShaderIndexingCase.prototype.setupUniforms = function(programID, constCoords) {
196         /** @type {(Array<number>|Float32Array)} */ var arr = [];
197         /** @type {Array<number>} */ var array1d = [];
198         /** @type {?WebGLUniformLocation} */ var arrLoc = gl.getUniformLocation(programID, 'u_arr');
199         if (arrLoc != null) {
200             if (this.m_varType === gluShaderUtil.DataType.FLOAT) {
201                 arr[0] = constCoords[0];
202                 arr[1] = constCoords[0] * 0.5;
203                 arr[2] = constCoords[0] * 0.25;
204                 arr[3] = constCoords[0] * 0.125;
205                 gl.uniform1fv(arrLoc, arr);
206             }
207             else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC2) {
208                 arr[0] = deMath.swizzle(constCoords, [0, 1]);
209                 arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.5);
210                 arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.25);
211                 arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.125);
212                 for (var i = 0; i < arr.length; i++)
213                     array1d = array1d.concat(arr[i]);
214                 gl.uniform2fv(arrLoc, array1d);
215             }
216             else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC3) {
217                 arr[0] = deMath.swizzle(constCoords, [0, 1, 2]);
218                 arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.5);
219                 arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.25);
220                 arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.125);
221                 for (var i = 0; i < arr.length; i++)
222                     array1d = array1d.concat(arr[i]);
223                 gl.uniform3fv(arrLoc, array1d);
224             }
225             else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC4) {
226                 arr[0] = deMath.swizzle(constCoords, [0,1,2,3]);
227                 arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.5);
228                 arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.25);
229                 arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.125);
230                 for (var i = 0; i < arr.length; i++)
231                     array1d = array1d.concat(arr[i]);
232                 gl.uniform4fv(arrLoc, array1d);
233             }
234             else
235                 throw new Error('u_arr should not have location assigned in this test case');
236         }
237     };
239     /**
240      * @param  {string} caseName
241      * @param  {string} description
242      * @param  {gluShaderUtil.DataType} varType
243      * @param  {es3fShaderIndexingTests.IndexAccessType} vertAccess
244      * @param  {es3fShaderIndexingTests.IndexAccessType} fragAccess
245      * @return {es3fShaderIndexingTests.ShaderIndexingCase}
246      */
247     es3fShaderIndexingTests.createVaryingArrayCase = function(caseName, description, varType, vertAccess, fragAccess) {
248         /** @type {string} */ var vtx = '';
249         vtx += '#version 300 es\n' +
250                'in highp vec4 a_position;\n' +
251                'in highp vec4 a_coords;\n';
253         if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
254             vtx += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
255         else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
256             vtx += 'uniform mediump int ui_four;\n';
258         vtx += 'out ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' +
259                '\n' +
260                'void main()\n' +
261                '{\n' +
262                '    gl_Position = a_position;\n';
264         if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
265             vtx += '    var[0] = ${VAR_TYPE}(a_coords);\n' +
266                    '    var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n' +
267                    '    var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n' +
268                    '    var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n';
269         }
270         else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
271             vtx += '    var[ui_zero]  = ${VAR_TYPE}(a_coords);\n' +
272                    '    var[ui_one]   = ${VAR_TYPE}(a_coords) * 0.5;\n' +
273                    '    var[ui_two]   = ${VAR_TYPE}(a_coords) * 0.25;\n' +
274                    '    var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n';
275         }
276         else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
277             vtx += '    ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' +
278                    '    for (int i = 0; i < 4; i++)\n' +
279                    '    {\n' +
280                    '            var[i] = ${VAR_TYPE}(coords);\n' +
281                    '        coords = coords * 0.5;\n' +
282                    '    }\n';
283         }
284         else {
285             assertMsgOptions(vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true);
286             vtx += '    ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' +
287                    '    for (int i = 0; i < ui_four; i++)\n' +
288                    '    {\n' +
289                    '            var[i] = ${VAR_TYPE}(coords);\n' +
290                    '        coords = coords * 0.5;\n' +
291                    '    }\n';
292         }
293         vtx += '}\n';
295         /** @type {string} */ var frag = '';
296         frag += '#version 300 es\n' +
297                 'precision mediump int;\n' +
298                 'layout(location = 0) out mediump vec4 o_color;\n';
300         if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
301             frag += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
302         else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
303             frag += 'uniform int ui_four;\n';
305         frag += 'in ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' +
306                 '\n' +
307                 'void main()\n' +
308                 '{\n' +
309                 '       ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n';
311         if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
312             frag += '    res += var[0];\n' +
313                     '    res += var[1];\n' +
314                     '    res += var[2];\n' +
315                     '    res += var[3];\n';
316         }
317         else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
318             frag += '    res += var[ui_zero];\n' +
319                     '    res += var[ui_one];\n' +
320                     '    res += var[ui_two];\n' +
321                     '    res += var[ui_three];\n';
322         }
323         else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
324             frag += '    for (int i = 0; i < 4; i++)\n' +
325                     '        res += var[i];\n';
326         }
327         else {
328             assertMsgOptions(fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true);
329             frag += '    for (int i = 0; i < ui_four; i++)\n' +
330                     '        res += var[i];\n';
331         }
332         frag += '       o_color = vec4(res${PADDING});\n' +
333                 '}\n';
335         // Fill in shader templates.
336         /** @type {Object} */ var params = {};
337             params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType);
338             params['ARRAY_LEN'] = '4';
339             params['PRECISION'] = 'mediump';
341         if (varType === gluShaderUtil.DataType.FLOAT)
342             params['PADDING'] = ', 0.0, 0.0, 1.0';
343         else if (varType === gluShaderUtil.DataType.FLOAT_VEC2)
344             params['PADDING'] = ', 0.0, 1.0';
345         else if (varType === gluShaderUtil.DataType.FLOAT_VEC3)
346             params['PADDING'] = ', 1.0';
347         else
348             params['PADDING'] = '';
350         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
351         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
353         /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
354         var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType);
355         return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, true, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
356     };
358     /**
359      * @param {string} caseName
360      * @param {string} description
361      * @param {boolean} isVertexCase
362      * @param {gluShaderUtil.DataType} varType
363      * @param {es3fShaderIndexingTests.IndexAccessType} readAccess
364      * @return {es3fShaderIndexingTests.ShaderIndexingCase}
365      */
366     es3fShaderIndexingTests.createUniformArrayCase = function(caseName, description, isVertexCase, varType, readAccess) {
367         /** @type {string} */ var vtx = '';
368         /** @type {string} */ var frag = '';
369         /** @type {string} */ var op = '';
371         vtx += '#version 300 es\n';
372         frag += '#version 300 es\n';
374         vtx += 'in highp vec4 a_position;\n';
375         vtx += 'in highp vec4 a_coords;\n';
376         frag += 'layout(location = 0) out mediump vec4 o_color;\n';
378         if (isVertexCase) {
379             vtx += 'out mediump vec4 v_color;\n';
380             frag += 'in mediump vec4 v_color;\n';
381         }
382         else {
383             vtx += 'out mediump vec4 v_coords;\n';
384             frag += 'in mediump vec4 v_coords;\n';
385         }
387         if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
388             op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
389         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
390             op += 'uniform mediump int ui_four;\n';
392         op += 'uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n';
394         vtx += isVertexCase ? op : '';
395         frag += isVertexCase ? '' : op;
396         op = '';
398         vtx += '\n';
399         vtx += 'void main()\n';
400         vtx += '{\n';
401         vtx += '    gl_Position = a_position;\n';
403         frag += '\n';
404         frag += 'void main()\n';
405         frag += '{\n';
407         // Read array.
408         op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n';
409         if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
410             op += '    res += u_arr[0];\n';
411             op += '    res += u_arr[1];\n';
412             op += '    res += u_arr[2];\n';
413             op += '    res += u_arr[3];\n';
414         }
415         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
416             op += '    res += u_arr[ui_zero];\n';
417             op += '    res += u_arr[ui_one];\n';
418             op += '    res += u_arr[ui_two];\n';
419             op += '    res += u_arr[ui_three];\n';
420         }
421         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
422             op += '    for (int i = 0; i < 4; i++)\n';
423             op += '        res += u_arr[i];\n';
424         }
425         else {
426             assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true);
427             op += '    for (int i = 0; i < ui_four; i++)\n';
428             op += '        res += u_arr[i];\n';
429         }
431         vtx += isVertexCase ? op : '';
432         frag += isVertexCase ? '' : op;
433         op = '';
435         if (isVertexCase) {
436             vtx += '    v_color = vec4(res${PADDING});\n';
437             frag += '    o_color = v_color;\n';
438         }
439         else {
440             vtx += '    v_coords = a_coords;\n';
441             frag += '    o_color = vec4(res${PADDING});\n';
442         }
444         vtx += '}\n';
445         frag += '}\n';
447         // Fill in shader templates.
448         /** @type {Object} */ var params = {};
449             params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType);
450             params['ARRAY_LEN'] = '4';
451             params['PRECISION'] = 'mediump';
453         if (varType === gluShaderUtil.DataType.FLOAT)
454             params['PADDING'] = ', 0.0, 0.0, 1.0';
455         else if (varType === gluShaderUtil.DataType.FLOAT_VEC2)
456             params['PADDING'] = ', 0.0, 1.0';
457         else if (varType === gluShaderUtil.DataType.FLOAT_VEC3)
458             params['PADDING'] = ', 1.0';
459         else
460             params['PADDING'] = '';
463         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
464         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
466         /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
467         var evalFunc = es3fShaderIndexingTests.getArrayUniformEvalFunc(varType);
468         return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
469     };
471     /**
472      * @param {string} caseName
473      * @param {string} description
474      * @param {boolean} isVertexCase
475      * @param {gluShaderUtil.DataType} varType
476      * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess
477      * @param {es3fShaderIndexingTests.IndexAccessType} readAccess
478      * @return {es3fShaderIndexingTests.ShaderIndexingCase}
479      */
480     es3fShaderIndexingTests.createTmpArrayCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess)    {
481         /** @type {string} */ var vtx = '';
482         /** @type {string} */ var frag = '';
483         /** @type {string} */ var op = '';
485         vtx += '#version 300 es\n';
486         frag += '#version 300 es\n';
488         vtx += 'in highp vec4 a_position;\n' +
489                'in highp vec4 a_coords;\n';
490         frag += 'layout(location = 0) out mediump vec4 o_color;\n';
492         if (isVertexCase) {
493             vtx += 'out mediump vec4 v_color;\n';
494             frag += 'in mediump vec4 v_color;\n';
495         }
496         else {
497             vtx += 'out mediump vec4 v_coords;\n';
498             frag += 'in mediump vec4 v_coords;\n';
499         }
501         if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC)
502             op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n';
504         if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
505             op += 'uniform mediump int ui_four;\n';
507         vtx += isVertexCase ? op : '';
508         frag += isVertexCase ? '' : op;
509         op = '';
511         vtx += '\n' +
512                'void main()\n' +
513                '{\n' +
514                '    gl_Position = a_position;\n';
516         frag += '\n' +
517                 'void main()\n' +
518                 '{\n';
520         // Write array.
521         if (isVertexCase)
522             op += '     ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n';
523         else
524             op += '     ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n';
526         op += ' ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n';
527         if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
528             op += '     arr[0] = ${VAR_TYPE}(coords);\n' +
529                       ' arr[1] = ${VAR_TYPE}(coords) * 0.5;\n' +
530                       ' arr[2] = ${VAR_TYPE}(coords) * 0.25;\n' +
531                       ' arr[3] = ${VAR_TYPE}(coords) * 0.125;\n';
532         }
533         else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
534                 op += ' arr[ui_zero]  = ${VAR_TYPE}(coords);\n' +
535                       ' arr[ui_one]   = ${VAR_TYPE}(coords) * 0.5;\n' +
536                       ' arr[ui_two]   = ${VAR_TYPE}(coords) * 0.25;\n' +
537                       ' arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n';
538         }
539         else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
540             op += '    for (int i = 0; i < 4; i++)\n' +
541                   '    {\n' +
542                   '        arr[i] = ${VAR_TYPE}(coords);\n' +
543                   '        coords = coords * 0.5;\n' +
544                   '    }\n';
545         }
546         else {
547             assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true);
548             op += '    for (int i = 0; i < ui_four; i++)\n' +
549                   '    {\n' +
550                   '        arr[i] = ${VAR_TYPE}(coords);\n' +
551                   '        coords = coords * 0.5;\n' +
552                   '    }\n';
553         }
555         // Read array.
556         op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n';
557         if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
558             op += '    res += arr[0];\n' +
559                   '    res += arr[1];\n' +
560                   '    res += arr[2];\n' +
561                   '    res += arr[3];\n';
562         }
563         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
564             op += '    res += arr[ui_zero];\n' +
565                   '    res += arr[ui_one];\n' +
566                   '    res += arr[ui_two];\n' +
567                   '    res += arr[ui_three];\n';
568         }
569         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
570             op += '    for (int i = 0; i < 4; i++)\n' +
571                   '        res += arr[i];\n';
572         }
573         else {
574             assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true);
575             op += '    for (int i = 0; i < ui_four; i++)\n' +
576                   '        res += arr[i];\n';
577         }
579         vtx += isVertexCase ? op : '';
580         frag += isVertexCase ? '' : op;
581         op = '';
583         if (isVertexCase) {
584             vtx += '    v_color = vec4(res${PADDING});\n';
585             frag += '    o_color = v_color;\n';
586         }
587         else {
588             vtx += '    v_coords = a_coords;\n';
589             frag += '    o_color = vec4(res${PADDING});\n';
590         }
592         vtx += '}\n';
593         frag += '}\n';
595         // Fill in shader templates.
596         /** @type {Object} */ var params = {};
597         params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType);
598         params["ARRAY_LEN"] = "4";
599         params["PRECISION"] = "mediump";
601         if (varType === gluShaderUtil.DataType.FLOAT)
602             params['PADDING'] = ', 0.0, 0.0, 1.0';
603         else if (varType === gluShaderUtil.DataType.FLOAT_VEC2)
604             params['PADDING'] = ', 0.0, 1.0';
605         else if (varType === gluShaderUtil.DataType.FLOAT_VEC3)
606             params['PADDING'] = ', 1.0';
607         else
608             params['PADDING'] = '';
610         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
611         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
613         /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
614         var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType);
615         return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
616     };
618     // VECTOR SUBSCRIPT.
620     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
621     es3fShaderIndexingTests.evalSubscriptVec2 = function(c) {
622         c.color[0] = c.coords[0] + 0.5 * c.coords[1];
623         c.color[1] = c.coords[0] + 0.5 * c.coords[1];
624         c.color[2] = c.coords[0] + 0.5 * c.coords[1];
625     };
626     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
627     es3fShaderIndexingTests.evalSubscriptVec3 = function(c) {
628         c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2];
629         c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2];
630         c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2];
631     };
632     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
633     es3fShaderIndexingTests.evalSubscriptVec4 = function(c) {
634         c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3];
635         c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3];
636         c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3];
637     };
639     /**
640      * @param {gluShaderUtil.DataType} dataType
641      * @return {function(glsShaderRenderCase.ShaderEvalContext)}
642      */
643     es3fShaderIndexingTests.getVectorSubscriptEvalFunc = function(dataType) {
644         if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalSubscriptVec2;
645         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalSubscriptVec3;
646         else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalSubscriptVec4;
647         else throw new Error('Invalid data type.');
648     };
650     /**
651      * @param {string} caseName
652      * @param {string} description
653      * @param {boolean} isVertexCase
654      * @param {gluShaderUtil.DataType} varType
655      * @param {es3fShaderIndexingTests.VectorAccessType} writeAccess
656      * @param {es3fShaderIndexingTests.VectorAccessType} readAccess
657      * @return {es3fShaderIndexingTests.ShaderIndexingCase}
658      */
659     es3fShaderIndexingTests.createVectorSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) {
660         /** @type {string} */ var vtx = '';
661         /** @type {string} */ var frag = '';
662         /** @type {string} */ var op = '' ;
664         /** @type {number} */ var vecLen = gluShaderUtil.getDataTypeScalarSize(varType);
665         /** @type {string} */ var vecLenName = glsShaderRenderCase.getIntUniformName(vecLen);
667         vtx += '#version 300 es\n';
668         frag += '#version 300 es\n';
670         vtx += 'in highp vec4 a_position;\n' +
671                'in highp vec4 a_coords;\n';
672         frag += 'layout(location = 0) out mediump vec4 o_color;\n';
674         if (isVertexCase) {
675             vtx += 'out mediump vec3 v_color;\n';
676             frag += 'in mediump vec3 v_color;\n';
677         }
678         else {
679             vtx += 'out mediump vec4 v_coords;\n';
680             frag += 'in mediump vec4 v_coords;\n';
681         }
683         if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC ||
684             readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC){
685             op += 'uniform mediump int ui_zero';
686             if (vecLen >= 2) op += ', ui_one';
687             if (vecLen >= 3) op += ', ui_two';
688             if (vecLen >= 4) op += ', ui_three';
689             op += ';\n';
690         }
692         if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP ||
693             readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP)
694             op += 'uniform mediump int ' + vecLenName + ';\n';
696         vtx += isVertexCase ? op : '';
697         frag += isVertexCase ? '' : op;
698         op = '';
700         vtx += '\n' +
701                'void main()\n' +
702                '{\n' +
703                '    gl_Position = a_position;\n';
705         frag += '\n' +
706                 'void main()\n' +
707                 '{\n';
709         // Write vector.
710         if (isVertexCase)
711             op += '     ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n';
712         else
713             op += '     ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n';
715         op += ' ${PRECISION} ${VAR_TYPE} tmp;\n';
716         if (writeAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT)
717             op += '    tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n';
718         else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) {
719             op += '    tmp.x = coords.x;\n';
720             if (vecLen >= 2) op += '    tmp.y = coords.y * 0.5;\n';
721             if (vecLen >= 3) op += '    tmp.z = coords.z * 0.25;\n';
722             if (vecLen >= 4) op += '    tmp.w = coords.w * 0.125;\n';
723         }
724         else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) {
725             op += '    tmp[0] = coords.x;\n';
726             if (vecLen >= 2) op += '    tmp[1] = coords.y * 0.5;\n';
727             if (vecLen >= 3) op += '    tmp[2] = coords.z * 0.25;\n';
728             if (vecLen >= 4) op += '    tmp[3] = coords.w * 0.125;\n';
729         }
730         else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) {
731             op += '    tmp[ui_zero]  = coords.x;\n';
732             if (vecLen >= 2) op += '    tmp[ui_one]   = coords.y * 0.5;\n';
733             if (vecLen >= 3) op += '    tmp[ui_two]   = coords.z * 0.25;\n';
734             if (vecLen >= 4) op += '    tmp[ui_three] = coords.w * 0.125;\n';
735         }
736         else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) {
737             op += '    for (int i = 0; i < ' + vecLen + '; i++)\n';
738             op += '    {\n';
739             op += '        tmp[i] = coords.x;\n';
740             op += '        coords = coords.${ROT_SWIZZLE} * 0.5;\n';
741             op += '    }\n';
742         }
743         else {
744             assertMsgOptions(writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'writeAccess not supported.', false, true);
745             op += '    for (int i = 0; i < ' + vecLenName + '; i++)\n';
746             op += '    {\n';
747             op += '        tmp[i] = coords.x;\n';
748             op += '        coords = coords.${ROT_SWIZZLE} * 0.5;\n';
749             op += '    }\n';
750         }
752         // Read vector.
753         op += ' ${PRECISION} float res = 0.0;\n';
754         if (readAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT)
755             op += '     res = dot(tmp, ${VAR_TYPE}(1.0));\n';
756         else if (readAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) {
757             op += '    res += tmp.x;\n';
758             if (vecLen >= 2) op += '    res += tmp.y;\n';
759             if (vecLen >= 3) op += '    res += tmp.z;\n';
760             if (vecLen >= 4) op += '    res += tmp.w;\n';
761         }
762         else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) {
763             op += '    res += tmp[0];\n';
764             if (vecLen >= 2) op += '    res += tmp[1];\n';
765             if (vecLen >= 3) op += '    res += tmp[2];\n';
766             if (vecLen >= 4) op += '    res += tmp[3];\n';
767         }
768         else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) {
769             op += '    res += tmp[ui_zero];\n';
770             if (vecLen >= 2) op += '    res += tmp[ui_one];\n';
771             if (vecLen >= 3) op += '    res += tmp[ui_two];\n';
772             if (vecLen >= 4) op += '    res += tmp[ui_three];\n';
773         }
774         else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) {
775             op += '    for (int i = 0; i < ' + vecLen + '; i++)\n';
776             op += '        res += tmp[i];\n';
777         }
778         else {
779             assertMsgOptions(readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'readAccess not supported', false, true);
780             op += '    for (int i = 0; i < ' + vecLenName + '; i++)\n';
781             op += '        res += tmp[i];\n';
782         }
784         vtx += isVertexCase ? op : '';
785         frag += isVertexCase ? '' : op;
786         op = '';
788         if (isVertexCase) {
789             vtx += '    v_color = vec3(res);\n';
790             frag += '    o_color = vec4(v_color.rgb, 1.0);\n';
791         }
792         else {
793             vtx += '    v_coords = a_coords;\n';
794             frag += '    o_color = vec4(vec3(res), 1.0);\n';
795         }
797         vtx += '}\n';
798         frag += '}\n';
800         // Fill in shader templates.
801         /** @type {Array<string>} */ var s_swizzles = ['', 'x', 'xy', 'xyz', 'xyzw'];
802         /** @type {Array<string>} */ var s_rotSwizzles = ['', 'x', 'yx', 'yzx', 'yzwx'];
804         /** @type {Object} */ var params = {};
805         params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType);
806             params["PRECISION"] = "mediump";
807             params["SWIZZLE"] = s_swizzles[vecLen];
808             params["ROT_SWIZZLE"] = s_rotSwizzles[vecLen];
810         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
811         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
813         /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
814         var evalFunc = es3fShaderIndexingTests.getVectorSubscriptEvalFunc(varType);
815         return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
816     };
818     // MATRIX SUBSCRIPT.
820     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
821     es3fShaderIndexingTests.evalSubscriptMat2 = function(c) {
822         var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
823         var swizzle12 = deMath.swizzle(c.coords, [1, 2]);
824         c.color[0] = swizzle01[0] + 0.5 * swizzle12[0];
825         c.color[1] = swizzle01[1] + 0.5 * swizzle12[1];
826     };
828     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
829     es3fShaderIndexingTests.evalSubscriptMat2x3 = function(c) {
830         var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
831         var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]);
832         c.color[0] = swizzle012[0] + 0.5 * swizzle123[0];
833         c.color[1] = swizzle012[1] + 0.5 * swizzle123[1];
834         c.color[2] = swizzle012[2] + 0.5 * swizzle123[2];
835     };
837     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
838     es3fShaderIndexingTests.evalSubscriptMat2x4 = function(c) {
839         c.color = deMath.add(
840             deMath.swizzle(c.coords, [0,1,2,3]),
841             deMath.scale(deMath.swizzle(c.coords, [1,2,3,0]), 0.5));
842     };
844     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
845     es3fShaderIndexingTests.evalSubscriptMat3x2 = function(c) {
846         var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
847         var swizzle12 = deMath.swizzle(c.coords, [1, 2]);
848         var swizzle23 = deMath.swizzle(c.coords, [2, 3]);
849         c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0];
850         c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1];
851     };
853     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
854     es3fShaderIndexingTests.evalSubscriptMat3 = function(c) {
855         var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
856         var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]);
857         var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]);
858         c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0];
859         c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1];
860         c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2];
861     };
863     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
864     es3fShaderIndexingTests.evalSubscriptMat3x4 = function(c) {
865         var swizzle0123 = deMath.swizzle(c.coords, [0, 1, 2, 3]);
866         var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]);
867         var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]);
868         c.color = deMath.add(
869             swizzle0123,
870             deMath.add(
871                 deMath.scale(swizzle1230, 0.5),
872                 deMath.scale(swizzle2301, 0.25)));
873     };
875     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
876     es3fShaderIndexingTests.evalSubscriptMat4x2 = function(c) {
877         var swizzle01 = deMath.swizzle(c.coords, [0, 1]);
878         var swizzle12 = deMath.swizzle(c.coords, [1, 2]);
879         var swizzle23 = deMath.swizzle(c.coords, [2, 3]);
880         var swizzle30 = deMath.swizzle(c.coords, [3, 0]);
881         c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0] + 0.125 * swizzle30[0];
882         c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1] + 0.125 * swizzle30[1];
883     };
885     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
886     es3fShaderIndexingTests.evalSubscriptMat4x3 = function(c) {
887         var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]);
888         var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]);
889         var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]);
890         var swizzle301 = deMath.swizzle(c.coords, [3, 0, 1]);
891         c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0] + 0.125 * swizzle301[0];
892         c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1] + 0.125 * swizzle301[1];
893         c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2] + 0.125 * swizzle301[2];
894     };
896     /** @param {glsShaderRenderCase.ShaderEvalContext} c */
897     es3fShaderIndexingTests.evalSubscriptMat4 = function(c) {
898         var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]);
899         var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]);
900         var swizzle3012 = deMath.swizzle(c.coords, [3, 0, 1, 2]);
901         c.color = deMath.add(
902             c.coords,
903             deMath.add(
904                 deMath.scale(swizzle1230, 0.5),
905                 deMath.add(
906                     deMath.scale(swizzle2301, 0.25),
907                     deMath.scale(swizzle3012, 0.125))));
908     };
910     /**
911      * @param  {gluShaderUtil.DataType} dataType
912      * @return {function(glsShaderRenderCase.ShaderEvalContext)}
913      */
914     es3fShaderIndexingTests.getMatrixSubscriptEvalFunc = function(dataType) {
915         switch (dataType) {
916             case gluShaderUtil.DataType.FLOAT_MAT2: return es3fShaderIndexingTests.evalSubscriptMat2;
917             case gluShaderUtil.DataType.FLOAT_MAT2X3: return es3fShaderIndexingTests.evalSubscriptMat2x3;
918             case gluShaderUtil.DataType.FLOAT_MAT2X4: return es3fShaderIndexingTests.evalSubscriptMat2x4;
919             case gluShaderUtil.DataType.FLOAT_MAT3X2: return es3fShaderIndexingTests.evalSubscriptMat3x2;
920             case gluShaderUtil.DataType.FLOAT_MAT3: return es3fShaderIndexingTests.evalSubscriptMat3;
921             case gluShaderUtil.DataType.FLOAT_MAT3X4: return es3fShaderIndexingTests.evalSubscriptMat3x4;
922             case gluShaderUtil.DataType.FLOAT_MAT4X2: return es3fShaderIndexingTests.evalSubscriptMat4x2;
923             case gluShaderUtil.DataType.FLOAT_MAT4X3: return es3fShaderIndexingTests.evalSubscriptMat4x3;
924             case gluShaderUtil.DataType.FLOAT_MAT4: return es3fShaderIndexingTests.evalSubscriptMat4;
925             default:
926                 throw new Error('Invalid data type.');
927         }
928     };
930     /**
931      * @param {string} caseName
932      * @param {string} description
933      * @param {boolean} isVertexCase
934      * @param {gluShaderUtil.DataType} varType
935      * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess
936      * @param {es3fShaderIndexingTests.IndexAccessType} readAccess
937      * @return {es3fShaderIndexingTests.ShaderIndexingCase}
938      */
939     es3fShaderIndexingTests.createMatrixSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) {
940         /** @type {string} */ var vtx = '';
941         /** @type {string} */ var frag = '';
942         /** @type {string} */ var op = '';
944         /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(varType);
945         /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(varType);
946         /** @type {string} */ var matSizeName = glsShaderRenderCase.getIntUniformName(numCols);
947         /** @type {gluShaderUtil.DataType} */ var vecType = gluShaderUtil.getDataTypeFloatVec(numRows);
949         vtx += '#version 300 es\n';
950         frag += '#version 300 es\n';
952         vtx += 'in highp vec4 a_position;\n' +
953                'in highp vec4 a_coords;\n';
954         frag += 'layout(location = 0) out mediump vec4 o_color;\n';
956         if (isVertexCase) {
957             vtx += 'out mediump vec4 v_color;\n';
958             frag += 'in mediump vec4 v_color;\n';
959         }
960         else {
961             vtx += 'out mediump vec4 v_coords;\n';
962             frag += 'in mediump vec4 v_coords;\n';
963         }
965         if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
966             op += 'uniform mediump int ui_zero';
967             if (numCols >= 2) op += ', ui_one';
968             if (numCols >= 3) op += ', ui_two';
969             if (numCols >= 4) op += ', ui_three';
970             op += ';\n';
971         }
973         if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP)
974             op += 'uniform mediump int ' + matSizeName + ';\n';
976         vtx += isVertexCase ? op : '';
977         frag += isVertexCase ? '' : op;
978         op = '';
980         vtx += '\n' +
981                'void main()\n' +
982                '{\n' +
983                '    gl_Position = a_position;\n';
985         frag += '\n' +
986                 'void main()\n' +
987                 '{\n';
989         // Write matrix.
990         if (isVertexCase)
991             op += '     ${PRECISION} vec4 coords = a_coords;\n';
992         else
993             op += '     ${PRECISION} vec4 coords = v_coords;\n';
995         op += ' ${PRECISION} ${MAT_TYPE} tmp;\n';
996         if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
997             op += '     tmp[0] = ${VEC_TYPE}(coords);\n';
998             if (numCols >= 2) op += '    tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n';
999             if (numCols >= 3) op += '    tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n';
1000             if (numCols >= 4) op += '    tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n';
1001         }
1002         else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
1003             op += '     tmp[ui_zero]  = ${VEC_TYPE}(coords);\n';
1004             if (numCols >= 2) op += '    tmp[ui_one]   = ${VEC_TYPE}(coords.yzwx) * 0.5;\n';
1005             if (numCols >= 3) op += '    tmp[ui_two]   = ${VEC_TYPE}(coords.zwxy) * 0.25;\n';
1006             if (numCols >= 4) op += '    tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n';
1007         }
1008         else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
1009             op += '    for (int i = 0; i < ' + numCols + '; i++)\n';
1010             op += '    {\n';
1011             op += '             tmp[i] = ${VEC_TYPE}(coords);\n';
1012             op += '        coords = coords.yzwx * 0.5;\n';
1013             op += '    }\n';
1014         }
1015         else {
1016             assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true);
1017             op += '    for (int i = 0; i < ' + matSizeName + '; i++)\n';
1018             op += '    {\n';
1019             op += '        tmp[i] = ${VEC_TYPE}(coords);\n';
1020             op += '        coords = coords.yzwx * 0.5;\n';
1021             op += '    }\n';
1022         }
1024         // Read matrix.
1025         op += ' ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n';
1026         if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) {
1027             op += '    res += tmp[0];\n';
1028             if (numCols >= 2) op += '    res += tmp[1];\n';
1029             if (numCols >= 3) op += '    res += tmp[2];\n';
1030             if (numCols >= 4) op += '    res += tmp[3];\n';
1031         }
1032         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) {
1033             op += '    res += tmp[ui_zero];\n';
1034             if (numCols >= 2) op += '    res += tmp[ui_one];\n';
1035             if (numCols >= 3) op += '    res += tmp[ui_two];\n';
1036             if (numCols >= 4) op += '    res += tmp[ui_three];\n';
1037         }
1038         else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) {
1039             op += '    for (int i = 0; i < ' + numCols + '; i++)\n';
1040             op += '        res += tmp[i];\n';
1041         }
1042         else {
1043             assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported', false, true);
1044             op += '    for (int i = 0; i < ' + matSizeName + '; i++)\n';
1045             op += '        res += tmp[i];\n';
1046         }
1048         vtx += isVertexCase ? op : '';
1049         frag += isVertexCase ? '' : op;
1050         op = '';
1052         if (isVertexCase) {
1053             vtx += '    v_color = vec4(res${PADDING});\n';
1054             frag += '    o_color = v_color;\n';
1055         }
1056         else {
1057             vtx += '    v_coords = a_coords;\n';
1058             frag += '    o_color = vec4(res${PADDING});\n';
1059         }
1061         vtx += '}\n';
1062         frag += '}\n';
1064         // Fill in shader templates.
1066         /** @type {Object} */ var params = {};
1067         params['MAT_TYPE'] = gluShaderUtil.getDataTypeName(varType);
1068         params['VEC_TYPE'] = gluShaderUtil.getDataTypeName(vecType);
1069         params['PRECISION'] = "mediump";
1072         if (numRows === 2)
1073               params['PADDING'] = ', 0.0, 1.0';
1074         else if (numRows === 3)
1075               params['PADDING'] = ', 1.0';
1076         else
1077               params['PADDING'] = '';
1079         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
1080         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
1082         /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */
1083         var evalFunc = es3fShaderIndexingTests.getMatrixSubscriptEvalFunc(varType);
1084         return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource);
1085     };
1087     /**
1088      * @constructor
1089      * @extends {tcuTestCase.DeqpTest}
1090      */
1091     es3fShaderIndexingTests.ShaderIndexingTests = function() {
1092         tcuTestCase.DeqpTest.call(this, 'indexing', 'Indexing Tests');
1093     };
1095     es3fShaderIndexingTests.ShaderIndexingTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
1096     es3fShaderIndexingTests.ShaderIndexingTests.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingTests;
1098     es3fShaderIndexingTests.ShaderIndexingTests.prototype.init = function() {
1099         var testGroup = tcuTestCase.runner.testCases;
1100         /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [
1101             gluShaderProgram.shaderType.VERTEX,
1102             gluShaderProgram.shaderType.FRAGMENT
1103         ];
1104         /** @type {Array<gluShaderUtil.DataType>} */ var s_floatAndVecTypes = [
1105             gluShaderUtil.DataType.FLOAT,
1106             gluShaderUtil.DataType.FLOAT_VEC2,
1107             gluShaderUtil.DataType.FLOAT_VEC3,
1108             gluShaderUtil.DataType.FLOAT_VEC4
1109         ];
1110         /** @type {string} */ var name;
1111         /** @type {string} */ var desc;
1112         /** @type {string} */ var shaderTypeName;
1113         /** @type {boolean} */ var isVertexCase;
1114         /** @type {gluShaderProgram.shaderType} */ var shaderType;
1115         /** @type {string} */ var writeAccessName;
1116         /** @type {string} */ var readAccessName;
1117         // Varying array access cases.
1118         /** @type {tcuTestCase.DeqpTest} */ var varyingGroup = tcuTestCase.newTest('varying_array', 'Varying array access tests.');
1119         testGroup.addChild(varyingGroup);
1120         /** @type {gluShaderUtil.DataType} */ var varType;
1121         for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) {
1122             varType = s_floatAndVecTypes[typeNdx];
1123             for (var vertAccessStr in es3fShaderIndexingTests.IndexAccessType) {
1124                 for (var fragAccessStr in es3fShaderIndexingTests.IndexAccessType) {
1125                     var vertAccess = es3fShaderIndexingTests.IndexAccessType[vertAccessStr];
1126                     var fragAccess = es3fShaderIndexingTests.IndexAccessType[fragAccessStr];
1127                     /** @type {string} */ var vertAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(vertAccess);
1128                     /** @type {string} */ var fragAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(fragAccess);
1129                     name = gluShaderUtil.getDataTypeName(varType) + '_' + vertAccessName + '_write_' + fragAccessName + '_read';
1130                     desc = 'Varying array with ' + vertAccessName + ' write in vertex shader and ' + fragAccessName + ' read in fragment shader.';
1131                     varyingGroup.addChild(es3fShaderIndexingTests.createVaryingArrayCase(name, desc, varType, vertAccess, fragAccess));
1132                 }
1133             }
1134         }
1136         // Uniform array access cases.
1137         /** @type {tcuTestCase.DeqpTest} */ var uniformGroup = tcuTestCase.newTest("uniform_array", "Uniform array access tests.");
1138         testGroup.addChild(uniformGroup);
1140         for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) {
1141             varType = s_floatAndVecTypes[typeNdx];
1142             for (var readAccessStr in es3fShaderIndexingTests.IndexAccessType) {
1143                 var readAccess = es3fShaderIndexingTests.IndexAccessType[readAccessStr];
1144                 readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(readAccess);
1145                 for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
1146                     shaderType = s_shaderTypes[shaderTypeNdx];
1147                     shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
1148                     name = gluShaderUtil.getDataTypeName(varType) + "_" + readAccessName + "_read_" + shaderTypeName;
1149                     desc = "Uniform array with " + readAccessName + " read in " + shaderTypeName + " shader.";
1150                     isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
1151                     uniformGroup.addChild(es3fShaderIndexingTests.createUniformArrayCase(name, desc, isVertexCase, varType, readAccess));
1152                 }
1153             }
1154         }
1156         // Temporary array access cases.
1157         /** @type {tcuTestCase.DeqpTest} */ var tmpGroup = tcuTestCase.newTest("tmp_array", "Temporary array access tests.");
1158         testGroup.addChild(tmpGroup);
1160         for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) {
1161             varType = s_floatAndVecTypes[typeNdx];
1162             for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) {
1163                 for (var readAccess in es3fShaderIndexingTests.IndexAccessType) {
1164                     writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]);
1165                     readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]);
1167                     for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
1168                         shaderType = s_shaderTypes[shaderTypeNdx];
1169                         shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
1170                         name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
1171                         desc = "Temporary array with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
1172                         isVertexCase = (shaderType === gluShaderProgram.shaderType.VERTEX);
1173                         tmpGroup.addChild(es3fShaderIndexingTests.createTmpArrayCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess]));
1174                     }
1175                 }
1176             }
1177         }
1179         // Vector indexing with subscripts.
1181         /** @type {Array<gluShaderUtil.DataType>} */ var s_vectorTypes = [
1182             gluShaderUtil.DataType.FLOAT_VEC2,
1183             gluShaderUtil.DataType.FLOAT_VEC3,
1184             gluShaderUtil.DataType.FLOAT_VEC4
1185         ];
1187         for (var typeNdx = 0; typeNdx < s_vectorTypes.length; typeNdx++) {
1188             /** @type {tcuTestCase.DeqpTest} */ var vecGroup = tcuTestCase.newTest("vector_subscript", "Vector subscript indexing.");
1189             testGroup.addChild(vecGroup);
1191             varType = s_vectorTypes[typeNdx];
1192             for (var writeAccess in es3fShaderIndexingTests.VectorAccessType) {
1193                 for (var readAccess in es3fShaderIndexingTests.VectorAccessType) {
1194                     writeAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[writeAccess]);
1195                     readAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[readAccess]);
1197                     for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
1198                         shaderType = s_shaderTypes[shaderTypeNdx];
1199                         shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
1200                         name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
1201                         desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
1202                         isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
1203                         vecGroup.addChild(es3fShaderIndexingTests.createVectorSubscriptCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.VectorAccessType[writeAccess], es3fShaderIndexingTests.VectorAccessType[readAccess]));
1204                     }
1205                 }
1206             }
1207         }
1209         // Matrix indexing with subscripts.
1210         /** @type {Array<tcuTestCase.DeqpTest>} */ var matGroup = [
1211             tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."),
1212             tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."),
1213             tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."),
1214         ];
1215         for (var ii = 0; ii < matGroup.length; ++ii) {
1216             testGroup.addChild(matGroup[ii]);
1217         }
1219         /** @type {Array<gluShaderUtil.DataType>} */ var s_matrixTypes = [
1220             gluShaderUtil.DataType.FLOAT_MAT2,
1221             gluShaderUtil.DataType.FLOAT_MAT2X3,
1222             gluShaderUtil.DataType.FLOAT_MAT2X4,
1223             gluShaderUtil.DataType.FLOAT_MAT3X2,
1224             gluShaderUtil.DataType.FLOAT_MAT3,
1225             gluShaderUtil.DataType.FLOAT_MAT3X4,
1226             gluShaderUtil.DataType.FLOAT_MAT4X2,
1227             gluShaderUtil.DataType.FLOAT_MAT4X3,
1228             gluShaderUtil.DataType.FLOAT_MAT4
1229         ];
1231         for (var typeNdx = 0; typeNdx < s_matrixTypes.length; typeNdx++) {
1232             varType = s_matrixTypes[typeNdx];
1233             for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) {
1234                 for (var readAccess in es3fShaderIndexingTests.IndexAccessType) {
1235                     writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]);
1236                     readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]);
1238                     for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
1239                         shaderType = s_shaderTypes[shaderTypeNdx];
1240                         shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
1241                         name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
1242                         desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
1243                         isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX;
1244                         matGroup[typeNdx % matGroup.length].addChild(es3fShaderIndexingTests.createMatrixSubscriptCase(
1245                             name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess]));
1246                     }
1247                 }
1248             }
1249         }
1250     };
1252     /**
1253      * Run test
1254      * @param {WebGL2RenderingContext} context
1255      */
1256     es3fShaderIndexingTests.run = function(context, range) {
1257         gl = context;
1258         //Set up Test Root parameters
1259         var state = tcuTestCase.runner;
1260         state.setRoot(new es3fShaderIndexingTests.ShaderIndexingTests());
1262         //Set up name and description of this test series.
1263         setCurrentTestName(state.testCases.fullName());
1264         description(state.testCases.getDescription());
1266         try {
1267             if (range)
1268                 state.setRange(range);
1269             //Run test cases
1270             tcuTestCase.runTestCases();
1271         }
1272         catch (err) {
1273             testFailedOptions('Failed to es3fShaderIndexingTests.run tests', false);
1274             tcuTestCase.runner.terminate();
1275         }
1276     };