am 80fe30bf: (-s ours) am 27ad6a99: Merge "Improve calibration and accouting in flush...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fShaderIndexingTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
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  *//*!
20  * \file
21  * \brief Shader indexing (arrays, vector, matrices) tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fShaderIndexingTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "gluShaderUtil.hpp"
27 #include "tcuStringTemplate.hpp"
28
29 #include "deInt32.h"
30 #include "deMemory.h"
31
32 #include <map>
33
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36
37 using namespace std;
38 using namespace tcu;
39 using namespace glu;
40 using namespace deqp::gls;
41
42 namespace deqp
43 {
44 namespace gles3
45 {
46 namespace Functional
47 {
48
49 enum IndexAccessType
50 {
51         INDEXACCESS_STATIC = 0,
52         INDEXACCESS_DYNAMIC,
53         INDEXACCESS_STATIC_LOOP,
54         INDEXACCESS_DYNAMIC_LOOP,
55
56         INDEXACCESS_LAST
57 };
58
59 static const char* getIndexAccessTypeName (IndexAccessType accessType)
60 {
61         static const char* s_names[INDEXACCESS_LAST] =
62         {
63                 "static",
64                 "dynamic",
65                 "static_loop",
66                 "dynamic_loop"
67         };
68
69         DE_ASSERT(deInBounds32((int)accessType, 0, INDEXACCESS_LAST));
70         return s_names[(int)accessType];
71 }
72
73 enum VectorAccessType
74 {
75         DIRECT = 0,
76         COMPONENT,
77         SUBSCRIPT_STATIC,
78         SUBSCRIPT_DYNAMIC,
79         SUBSCRIPT_STATIC_LOOP,
80         SUBSCRIPT_DYNAMIC_LOOP,
81
82         VECTORACCESS_LAST
83 };
84
85 static const char* getVectorAccessTypeName (VectorAccessType accessType)
86 {
87         static const char* s_names[VECTORACCESS_LAST] =
88         {
89                 "direct",
90                 "component",
91                 "static_subscript",
92                 "dynamic_subscript",
93                 "static_loop_subscript",
94                 "dynamic_loop_subscript"
95         };
96
97         DE_ASSERT(deInBounds32((int)accessType, 0, VECTORACCESS_LAST));
98         return s_names[(int)accessType];
99 }
100
101 void evalArrayCoordsFloat               (ShaderEvalContext& c) { c.color.x()    = 1.875f * c.coords.x(); }
102 void evalArrayCoordsVec2                (ShaderEvalContext& c) { c.color.xy()   = 1.875f * c.coords.swizzle(0,1); }
103 void evalArrayCoordsVec3                (ShaderEvalContext& c) { c.color.xyz()  = 1.875f * c.coords.swizzle(0,1,2); }
104 void evalArrayCoordsVec4                (ShaderEvalContext& c) { c.color                = 1.875f * c.coords; }
105
106 static ShaderEvalFunc getArrayCoordsEvalFunc (DataType dataType)
107 {
108         if (dataType == TYPE_FLOAT)                             return evalArrayCoordsFloat;
109         else if (dataType == TYPE_FLOAT_VEC2)   return evalArrayCoordsVec2;
110         else if (dataType == TYPE_FLOAT_VEC3)   return evalArrayCoordsVec3;
111         else if (dataType == TYPE_FLOAT_VEC4)   return evalArrayCoordsVec4;
112
113         DE_FATAL("Invalid data type.");
114         return NULL;
115 }
116
117 void evalArrayUniformFloat              (ShaderEvalContext& c) { c.color.x()    = 1.875f * c.constCoords.x(); }
118 void evalArrayUniformVec2               (ShaderEvalContext& c) { c.color.xy()   = 1.875f * c.constCoords.swizzle(0,1); }
119 void evalArrayUniformVec3               (ShaderEvalContext& c) { c.color.xyz()  = 1.875f * c.constCoords.swizzle(0,1,2); }
120 void evalArrayUniformVec4               (ShaderEvalContext& c) { c.color                = 1.875f * c.constCoords; }
121
122 static ShaderEvalFunc getArrayUniformEvalFunc (DataType dataType)
123 {
124         if (dataType == TYPE_FLOAT)                             return evalArrayUniformFloat;
125         else if (dataType == TYPE_FLOAT_VEC2)   return evalArrayUniformVec2;
126         else if (dataType == TYPE_FLOAT_VEC3)   return evalArrayUniformVec3;
127         else if (dataType == TYPE_FLOAT_VEC4)   return evalArrayUniformVec4;
128
129         DE_FATAL("Invalid data type.");
130         return NULL;
131 }
132
133 // ShaderIndexingCase
134
135 class ShaderIndexingCase : public ShaderRenderCase
136 {
137 public:
138                                                                 ShaderIndexingCase              (Context& context, const char* name, const char* description, bool isVertexCase, DataType varType, ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource);
139         virtual                                         ~ShaderIndexingCase             (void);
140
141 private:
142                                                                 ShaderIndexingCase              (const ShaderIndexingCase&);    // not allowed!
143         ShaderIndexingCase&                     operator=                               (const ShaderIndexingCase&);    // not allowed!
144
145         virtual void                            setup                                   (int programID);
146         virtual void                            setupUniforms                   (int programID, const Vec4& constCoords);
147
148         DataType                                        m_varType;
149 };
150
151 ShaderIndexingCase::ShaderIndexingCase (Context& context, const char* name, const char* description, bool isVertexCase, DataType varType, ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource)
152         : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc)
153 {
154         m_varType                       = varType;
155         m_vertShaderSource      = vertShaderSource;
156         m_fragShaderSource      = fragShaderSource;
157 }
158
159 ShaderIndexingCase::~ShaderIndexingCase (void)
160 {
161 }
162
163 void ShaderIndexingCase::setup (int programID)
164 {
165         DE_UNREF(programID);
166 }
167
168 void ShaderIndexingCase::setupUniforms (int programID, const Vec4& constCoords)
169 {
170         const glw::Functions& gl = m_renderCtx.getFunctions();
171
172         DE_UNREF(constCoords);
173
174         int arrLoc = gl.getUniformLocation(programID, "u_arr");
175         if (arrLoc != -1)
176         {
177                 //int scalarSize = getDataTypeScalarSize(m_varType);
178                 if (m_varType == TYPE_FLOAT)
179                 {
180                         float arr[4];
181                         arr[0] = constCoords.x();
182                         arr[1] = constCoords.x() * 0.5f;
183                         arr[2] = constCoords.x() * 0.25f;
184                         arr[3] = constCoords.x() * 0.125f;
185                         gl.uniform1fv(arrLoc, 4, &arr[0]);
186                 }
187                 else if (m_varType == TYPE_FLOAT_VEC2)
188                 {
189                         Vec2 arr[4];
190                         arr[0] = constCoords.swizzle(0,1);
191                         arr[1] = constCoords.swizzle(0,1) * 0.5f;
192                         arr[2] = constCoords.swizzle(0,1) * 0.25f;
193                         arr[3] = constCoords.swizzle(0,1) * 0.125f;
194                         gl.uniform2fv(arrLoc, 4, arr[0].getPtr());
195                 }
196                 else if (m_varType == TYPE_FLOAT_VEC3)
197                 {
198                         Vec3 arr[4];
199                         arr[0] = constCoords.swizzle(0,1,2);
200                         arr[1] = constCoords.swizzle(0,1,2) * 0.5f;
201                         arr[2] = constCoords.swizzle(0,1,2) * 0.25f;
202                         arr[3] = constCoords.swizzle(0,1,2) * 0.125f;
203                         gl.uniform3fv(arrLoc, 4, arr[0].getPtr());
204                 }
205                 else if (m_varType == TYPE_FLOAT_VEC4)
206                 {
207                         Vec4 arr[4];
208                         arr[0] = constCoords.swizzle(0,1,2,3);
209                         arr[1] = constCoords.swizzle(0,1,2,3) * 0.5f;
210                         arr[2] = constCoords.swizzle(0,1,2,3) * 0.25f;
211                         arr[3] = constCoords.swizzle(0,1,2,3) * 0.125f;
212                         gl.uniform4fv(arrLoc, 4, arr[0].getPtr());
213                 }
214                 else
215                         throw tcu::TestError("u_arr should not have location assigned in this test case");
216         }
217 }
218
219 // Helpers.
220
221 static ShaderIndexingCase* createVaryingArrayCase (Context& context, const char* caseName, const char* description, DataType varType, IndexAccessType vertAccess, IndexAccessType fragAccess)
222 {
223         std::ostringstream vtx;
224         vtx << "#version 300 es\n";
225         vtx << "in highp vec4 a_position;\n";
226         vtx << "in highp vec4 a_coords;\n";
227         if (vertAccess == INDEXACCESS_DYNAMIC)
228                 vtx << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
229         else if (vertAccess == INDEXACCESS_DYNAMIC_LOOP)
230                 vtx << "uniform mediump int ui_four;\n";
231         vtx << "out ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n";
232         vtx << "\n";
233         vtx << "void main()\n";
234         vtx << "{\n";
235         vtx << "        gl_Position = a_position;\n";
236         if (vertAccess == INDEXACCESS_STATIC)
237         {
238                 vtx << "        var[0] = ${VAR_TYPE}(a_coords);\n";
239                 vtx << "        var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n";
240                 vtx << "        var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n";
241                 vtx << "        var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n";
242         }
243         else if (vertAccess == INDEXACCESS_DYNAMIC)
244         {
245                 vtx << "        var[ui_zero]  = ${VAR_TYPE}(a_coords);\n";
246                 vtx << "        var[ui_one]   = ${VAR_TYPE}(a_coords) * 0.5;\n";
247                 vtx << "        var[ui_two]   = ${VAR_TYPE}(a_coords) * 0.25;\n";
248                 vtx << "        var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n";
249         }
250         else if (vertAccess == INDEXACCESS_STATIC_LOOP)
251         {
252                 vtx << "        ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
253                 vtx << "        for (int i = 0; i < 4; i++)\n";
254                 vtx << "        {\n";
255                 vtx << "                var[i] = ${VAR_TYPE}(coords);\n";
256                 vtx << "                coords = coords * 0.5;\n";
257                 vtx << "        }\n";
258         }
259         else
260         {
261                 DE_ASSERT(vertAccess == INDEXACCESS_DYNAMIC_LOOP);
262                 vtx << "        ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
263                 vtx << "        for (int i = 0; i < ui_four; i++)\n";
264                 vtx << "        {\n";
265                 vtx << "                var[i] = ${VAR_TYPE}(coords);\n";
266                 vtx << "                coords = coords * 0.5;\n";
267                 vtx << "        }\n";
268         }
269         vtx << "}\n";
270
271         std::ostringstream frag;
272         frag << "#version 300 es\n";
273         frag << "precision mediump int;\n";
274         frag << "layout(location = 0) out mediump vec4 o_color;\n";
275         if (fragAccess == INDEXACCESS_DYNAMIC)
276                 frag << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
277         else if (fragAccess == INDEXACCESS_DYNAMIC_LOOP)
278                 frag << "uniform int ui_four;\n";
279         frag << "in ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n";
280         frag << "\n";
281         frag << "void main()\n";
282         frag << "{\n";
283         frag << "       ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n";
284         if (fragAccess == INDEXACCESS_STATIC)
285         {
286                 frag << "       res += var[0];\n";
287                 frag << "       res += var[1];\n";
288                 frag << "       res += var[2];\n";
289                 frag << "       res += var[3];\n";
290         }
291         else if (fragAccess == INDEXACCESS_DYNAMIC)
292         {
293                 frag << "       res += var[ui_zero];\n";
294                 frag << "       res += var[ui_one];\n";
295                 frag << "       res += var[ui_two];\n";
296                 frag << "       res += var[ui_three];\n";
297         }
298         else if (fragAccess == INDEXACCESS_STATIC_LOOP)
299         {
300                 frag << "       for (int i = 0; i < 4; i++)\n";
301                 frag << "               res += var[i];\n";
302         }
303         else
304         {
305                 DE_ASSERT(fragAccess == INDEXACCESS_DYNAMIC_LOOP);
306                 frag << "       for (int i = 0; i < ui_four; i++)\n";
307                 frag << "               res += var[i];\n";
308         }
309         frag << "       o_color = vec4(res${PADDING});\n";
310         frag << "}\n";
311
312         // Fill in shader templates.
313         map<string, string> params;
314         params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
315         params.insert(pair<string, string>("ARRAY_LEN", "4"));
316         params.insert(pair<string, string>("PRECISION", "mediump"));
317
318         if (varType == TYPE_FLOAT)
319                 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0"));
320         else if (varType == TYPE_FLOAT_VEC2)
321                 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
322         else if (varType == TYPE_FLOAT_VEC3)
323                 params.insert(pair<string, string>("PADDING", ", 1.0"));
324         else
325                 params.insert(pair<string, string>("PADDING", ""));
326
327         StringTemplate vertTemplate(vtx.str().c_str());
328         StringTemplate fragTemplate(frag.str().c_str());
329         string vertexShaderSource = vertTemplate.specialize(params);
330         string fragmentShaderSource = fragTemplate.specialize(params);
331
332         ShaderEvalFunc evalFunc = getArrayCoordsEvalFunc(varType);
333         return new ShaderIndexingCase(context, caseName, description, true, varType, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str());
334 }
335
336 static ShaderIndexingCase* createUniformArrayCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, IndexAccessType readAccess)
337 {
338         std::ostringstream vtx;
339         std::ostringstream frag;
340         std::ostringstream& op = isVertexCase ? vtx : frag;
341
342         vtx << "#version 300 es\n";
343         frag << "#version 300 es\n";
344
345         vtx << "in highp vec4 a_position;\n";
346         vtx << "in highp vec4 a_coords;\n";
347         frag << "layout(location = 0) out mediump vec4 o_color;\n";
348
349         if (isVertexCase)
350         {
351                 vtx << "out mediump vec4 v_color;\n";
352                 frag << "in mediump vec4 v_color;\n";
353         }
354         else
355         {
356                 vtx << "out mediump vec4 v_coords;\n";
357                 frag << "in mediump vec4 v_coords;\n";
358         }
359
360         if (readAccess == INDEXACCESS_DYNAMIC)
361                 op << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
362         else if (readAccess == INDEXACCESS_DYNAMIC_LOOP)
363                 op << "uniform mediump int ui_four;\n";
364
365         op << "uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n";
366
367         vtx << "\n";
368         vtx << "void main()\n";
369         vtx << "{\n";
370         vtx << "        gl_Position = a_position;\n";
371
372         frag << "\n";
373         frag << "void main()\n";
374         frag << "{\n";
375
376         // Read array.
377         op << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n";
378         if (readAccess == INDEXACCESS_STATIC)
379         {
380                 op << " res += u_arr[0];\n";
381                 op << " res += u_arr[1];\n";
382                 op << " res += u_arr[2];\n";
383                 op << " res += u_arr[3];\n";
384         }
385         else if (readAccess == INDEXACCESS_DYNAMIC)
386         {
387                 op << " res += u_arr[ui_zero];\n";
388                 op << " res += u_arr[ui_one];\n";
389                 op << " res += u_arr[ui_two];\n";
390                 op << " res += u_arr[ui_three];\n";
391         }
392         else if (readAccess == INDEXACCESS_STATIC_LOOP)
393         {
394                 op << " for (int i = 0; i < 4; i++)\n";
395                 op << "         res += u_arr[i];\n";
396         }
397         else
398         {
399                 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
400                 op << " for (int i = 0; i < ui_four; i++)\n";
401                 op << "         res += u_arr[i];\n";
402         }
403
404         if (isVertexCase)
405         {
406                 vtx << "        v_color = vec4(res${PADDING});\n";
407                 frag << "       o_color = v_color;\n";
408         }
409         else
410         {
411                 vtx << "        v_coords = a_coords;\n";
412                 frag << "       o_color = vec4(res${PADDING});\n";
413         }
414
415         vtx << "}\n";
416         frag << "}\n";
417
418         // Fill in shader templates.
419         map<string, string> params;
420         params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
421         params.insert(pair<string, string>("ARRAY_LEN", "4"));
422         params.insert(pair<string, string>("PRECISION", "mediump"));
423
424         if (varType == TYPE_FLOAT)
425                 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0"));
426         else if (varType == TYPE_FLOAT_VEC2)
427                 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
428         else if (varType == TYPE_FLOAT_VEC3)
429                 params.insert(pair<string, string>("PADDING", ", 1.0"));
430         else
431                 params.insert(pair<string, string>("PADDING", ""));
432
433         StringTemplate vertTemplate(vtx.str().c_str());
434         StringTemplate fragTemplate(frag.str().c_str());
435         string vertexShaderSource = vertTemplate.specialize(params);
436         string fragmentShaderSource = fragTemplate.specialize(params);
437
438         ShaderEvalFunc evalFunc = getArrayUniformEvalFunc(varType);
439         return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str());
440 }
441
442 static ShaderIndexingCase* createTmpArrayCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, IndexAccessType writeAccess, IndexAccessType readAccess)
443 {
444         std::ostringstream vtx;
445         std::ostringstream frag;
446         std::ostringstream& op = isVertexCase ? vtx : frag;
447
448         vtx << "#version 300 es\n";
449         frag << "#version 300 es\n";
450
451         vtx << "in highp vec4 a_position;\n";
452         vtx << "in highp vec4 a_coords;\n";
453         frag << "layout(location = 0) out mediump vec4 o_color;\n";
454
455         if (isVertexCase)
456         {
457                 vtx << "out mediump vec4 v_color;\n";
458                 frag << "in mediump vec4 v_color;\n";
459         }
460         else
461         {
462                 vtx << "out mediump vec4 v_coords;\n";
463                 frag << "in mediump vec4 v_coords;\n";
464         }
465
466         if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC)
467                 op << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n";
468
469         if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP)
470                 op << "uniform mediump int ui_four;\n";
471
472         vtx << "\n";
473         vtx << "void main()\n";
474         vtx << "{\n";
475         vtx << "        gl_Position = a_position;\n";
476
477         frag << "\n";
478         frag << "void main()\n";
479         frag << "{\n";
480
481         // Write array.
482         if (isVertexCase)
483                 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
484         else
485                 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n";
486
487         op << " ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n";
488         if (writeAccess == INDEXACCESS_STATIC)
489         {
490                 op << " arr[0] = ${VAR_TYPE}(coords);\n";
491                 op << " arr[1] = ${VAR_TYPE}(coords) * 0.5;\n";
492                 op << " arr[2] = ${VAR_TYPE}(coords) * 0.25;\n";
493                 op << " arr[3] = ${VAR_TYPE}(coords) * 0.125;\n";
494         }
495         else if (writeAccess == INDEXACCESS_DYNAMIC)
496         {
497                 op << " arr[ui_zero]  = ${VAR_TYPE}(coords);\n";
498                 op << " arr[ui_one]   = ${VAR_TYPE}(coords) * 0.5;\n";
499                 op << " arr[ui_two]   = ${VAR_TYPE}(coords) * 0.25;\n";
500                 op << " arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n";
501         }
502         else if (writeAccess == INDEXACCESS_STATIC_LOOP)
503         {
504                 op << " for (int i = 0; i < 4; i++)\n";
505                 op << " {\n";
506                 op << "         arr[i] = ${VAR_TYPE}(coords);\n";
507                 op << "         coords = coords * 0.5;\n";
508                 op << " }\n";
509         }
510         else
511         {
512                 DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP);
513                 op << " for (int i = 0; i < ui_four; i++)\n";
514                 op << " {\n";
515                 op << "         arr[i] = ${VAR_TYPE}(coords);\n";
516                 op << "         coords = coords * 0.5;\n";
517                 op << " }\n";
518         }
519
520         // Read array.
521         op << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n";
522         if (readAccess == INDEXACCESS_STATIC)
523         {
524                 op << " res += arr[0];\n";
525                 op << " res += arr[1];\n";
526                 op << " res += arr[2];\n";
527                 op << " res += arr[3];\n";
528         }
529         else if (readAccess == INDEXACCESS_DYNAMIC)
530         {
531                 op << " res += arr[ui_zero];\n";
532                 op << " res += arr[ui_one];\n";
533                 op << " res += arr[ui_two];\n";
534                 op << " res += arr[ui_three];\n";
535         }
536         else if (readAccess == INDEXACCESS_STATIC_LOOP)
537         {
538                 op << " for (int i = 0; i < 4; i++)\n";
539                 op << "         res += arr[i];\n";
540         }
541         else
542         {
543                 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
544                 op << " for (int i = 0; i < ui_four; i++)\n";
545                 op << "         res += arr[i];\n";
546         }
547
548         if (isVertexCase)
549         {
550                 vtx << "        v_color = vec4(res${PADDING});\n";
551                 frag << "       o_color = v_color;\n";
552         }
553         else
554         {
555                 vtx << "        v_coords = a_coords;\n";
556                 frag << "       o_color = vec4(res${PADDING});\n";
557         }
558
559         vtx << "}\n";
560         frag << "}\n";
561
562         // Fill in shader templates.
563         map<string, string> params;
564         params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
565         params.insert(pair<string, string>("ARRAY_LEN", "4"));
566         params.insert(pair<string, string>("PRECISION", "mediump"));
567
568         if (varType == TYPE_FLOAT)
569                 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0"));
570         else if (varType == TYPE_FLOAT_VEC2)
571                 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
572         else if (varType == TYPE_FLOAT_VEC3)
573                 params.insert(pair<string, string>("PADDING", ", 1.0"));
574         else
575                 params.insert(pair<string, string>("PADDING", ""));
576
577         StringTemplate vertTemplate(vtx.str().c_str());
578         StringTemplate fragTemplate(frag.str().c_str());
579         string vertexShaderSource = vertTemplate.specialize(params);
580         string fragmentShaderSource = fragTemplate.specialize(params);
581
582         ShaderEvalFunc evalFunc = getArrayCoordsEvalFunc(varType);
583         return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str());
584 }
585
586 // VECTOR SUBSCRIPT.
587
588 void evalSubscriptVec2 (ShaderEvalContext& c) { c.color.xyz() = Vec3(c.coords.x() + 0.5f*c.coords.y()); }
589 void evalSubscriptVec3 (ShaderEvalContext& c) { c.color.xyz() = Vec3(c.coords.x() + 0.5f*c.coords.y() + 0.25f*c.coords.z()); }
590 void evalSubscriptVec4 (ShaderEvalContext& c) { c.color.xyz() = Vec3(c.coords.x() + 0.5f*c.coords.y() + 0.25f*c.coords.z() + 0.125f*c.coords.w()); }
591
592 static ShaderEvalFunc getVectorSubscriptEvalFunc (DataType dataType)
593 {
594         if (dataType == TYPE_FLOAT_VEC2)                return evalSubscriptVec2;
595         else if (dataType == TYPE_FLOAT_VEC3)   return evalSubscriptVec3;
596         else if (dataType == TYPE_FLOAT_VEC4)   return evalSubscriptVec4;
597
598         DE_FATAL("Invalid data type.");
599         return NULL;
600 }
601
602 static ShaderIndexingCase* createVectorSubscriptCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, VectorAccessType writeAccess, VectorAccessType readAccess)
603 {
604         std::ostringstream vtx;
605         std::ostringstream frag;
606         std::ostringstream& op = isVertexCase ? vtx : frag;
607
608         int                     vecLen          = getDataTypeScalarSize(varType);
609         const char*     vecLenName      = getIntUniformName(vecLen);
610
611         vtx << "#version 300 es\n";
612         frag << "#version 300 es\n";
613
614         vtx << "in highp vec4 a_position;\n";
615         vtx << "in highp vec4 a_coords;\n";
616         frag << "layout(location = 0) out mediump vec4 o_color;\n";
617
618         if (isVertexCase)
619         {
620                 vtx << "out mediump vec3 v_color;\n";
621                 frag << "in mediump vec3 v_color;\n";
622         }
623         else
624         {
625                 vtx << "out mediump vec4 v_coords;\n";
626                 frag << "in mediump vec4 v_coords;\n";
627         }
628
629         if (writeAccess == SUBSCRIPT_DYNAMIC || readAccess == SUBSCRIPT_DYNAMIC)
630         {
631                 op << "uniform mediump int ui_zero";
632                 if (vecLen >= 2) op << ", ui_one";
633                 if (vecLen >= 3) op << ", ui_two";
634                 if (vecLen >= 4) op << ", ui_three";
635                 op << ";\n";
636         }
637
638         if (writeAccess == SUBSCRIPT_DYNAMIC_LOOP || readAccess == SUBSCRIPT_DYNAMIC_LOOP)
639                 op << "uniform mediump int " << vecLenName << ";\n";
640
641         vtx << "\n";
642         vtx << "void main()\n";
643         vtx << "{\n";
644         vtx << "        gl_Position = a_position;\n";
645
646         frag << "\n";
647         frag << "void main()\n";
648         frag << "{\n";
649
650         // Write vector.
651         if (isVertexCase)
652                 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
653         else
654                 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n";
655
656         op << " ${PRECISION} ${VAR_TYPE} tmp;\n";
657         if (writeAccess == DIRECT)
658                 op << " tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n";
659         else if (writeAccess == COMPONENT)
660         {
661                 op << " tmp.x = coords.x;\n";
662                 if (vecLen >= 2) op << "        tmp.y = coords.y * 0.5;\n";
663                 if (vecLen >= 3) op << "        tmp.z = coords.z * 0.25;\n";
664                 if (vecLen >= 4) op << "        tmp.w = coords.w * 0.125;\n";
665         }
666         else if (writeAccess == SUBSCRIPT_STATIC)
667         {
668                 op << " tmp[0] = coords.x;\n";
669                 if (vecLen >= 2) op << "        tmp[1] = coords.y * 0.5;\n";
670                 if (vecLen >= 3) op << "        tmp[2] = coords.z * 0.25;\n";
671                 if (vecLen >= 4) op << "        tmp[3] = coords.w * 0.125;\n";
672         }
673         else if (writeAccess == SUBSCRIPT_DYNAMIC)
674         {
675                 op << " tmp[ui_zero]  = coords.x;\n";
676                 if (vecLen >= 2) op << "        tmp[ui_one]   = coords.y * 0.5;\n";
677                 if (vecLen >= 3) op << "        tmp[ui_two]   = coords.z * 0.25;\n";
678                 if (vecLen >= 4) op << "        tmp[ui_three] = coords.w * 0.125;\n";
679         }
680         else if (writeAccess == SUBSCRIPT_STATIC_LOOP)
681         {
682                 op << " for (int i = 0; i < " << vecLen << "; i++)\n";
683                 op << " {\n";
684                 op << "         tmp[i] = coords.x;\n";
685                 op << "         coords = coords.${ROT_SWIZZLE} * 0.5;\n";
686                 op << " }\n";
687         }
688         else
689         {
690                 DE_ASSERT(writeAccess == SUBSCRIPT_DYNAMIC_LOOP);
691                 op << " for (int i = 0; i < " << vecLenName << "; i++)\n";
692                 op << " {\n";
693                 op << "         tmp[i] = coords.x;\n";
694                 op << "         coords = coords.${ROT_SWIZZLE} * 0.5;\n";
695                 op << " }\n";
696         }
697
698         // Read vector.
699         op << " ${PRECISION} float res = 0.0;\n";
700         if (readAccess == DIRECT)
701                 op << " res = dot(tmp, ${VAR_TYPE}(1.0));\n";
702         else if (readAccess == COMPONENT)
703         {
704                 op << " res += tmp.x;\n";
705                 if (vecLen >= 2) op << "        res += tmp.y;\n";
706                 if (vecLen >= 3) op << "        res += tmp.z;\n";
707                 if (vecLen >= 4) op << "        res += tmp.w;\n";
708         }
709         else if (readAccess == SUBSCRIPT_STATIC)
710         {
711                 op << " res += tmp[0];\n";
712                 if (vecLen >= 2) op << "        res += tmp[1];\n";
713                 if (vecLen >= 3) op << "        res += tmp[2];\n";
714                 if (vecLen >= 4) op << "        res += tmp[3];\n";
715         }
716         else if (readAccess == SUBSCRIPT_DYNAMIC)
717         {
718                 op << " res += tmp[ui_zero];\n";
719                 if (vecLen >= 2) op << "        res += tmp[ui_one];\n";
720                 if (vecLen >= 3) op << "        res += tmp[ui_two];\n";
721                 if (vecLen >= 4) op << "        res += tmp[ui_three];\n";
722         }
723         else if (readAccess == SUBSCRIPT_STATIC_LOOP)
724         {
725                 op << " for (int i = 0; i < " << vecLen << "; i++)\n";
726                 op << "         res += tmp[i];\n";
727         }
728         else
729         {
730                 DE_ASSERT(readAccess == SUBSCRIPT_DYNAMIC_LOOP);
731                 op << " for (int i = 0; i < " << vecLenName << "; i++)\n";
732                 op << "         res += tmp[i];\n";
733         }
734
735         if (isVertexCase)
736         {
737                 vtx << "        v_color = vec3(res);\n";
738                 frag << "       o_color = vec4(v_color.rgb, 1.0);\n";
739         }
740         else
741         {
742                 vtx << "        v_coords = a_coords;\n";
743                 frag << "       o_color = vec4(vec3(res), 1.0);\n";
744         }
745
746         vtx << "}\n";
747         frag << "}\n";
748
749         // Fill in shader templates.
750         static const char* s_swizzles[5]        = { "", "x", "xy", "xyz", "xyzw" };
751         static const char* s_rotSwizzles[5]     = { "", "x", "yx", "yzx", "yzwx" };
752
753         map<string, string> params;
754         params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
755         params.insert(pair<string, string>("PRECISION", "mediump"));
756         params.insert(pair<string, string>("SWIZZLE", s_swizzles[vecLen]));
757         params.insert(pair<string, string>("ROT_SWIZZLE", s_rotSwizzles[vecLen]));
758
759         StringTemplate vertTemplate(vtx.str().c_str());
760         StringTemplate fragTemplate(frag.str().c_str());
761         string vertexShaderSource = vertTemplate.specialize(params);
762         string fragmentShaderSource = fragTemplate.specialize(params);
763
764         ShaderEvalFunc evalFunc = getVectorSubscriptEvalFunc(varType);
765         return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str());
766 }
767
768 // MATRIX SUBSCRIPT.
769
770 void evalSubscriptMat2          (ShaderEvalContext& c) { c.color.xy()   = c.coords.swizzle(0,1) + 0.5f*c.coords.swizzle(1,2); }
771 void evalSubscriptMat2x3        (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(0,1,2) + 0.5f*c.coords.swizzle(1,2,3); }
772 void evalSubscriptMat2x4        (ShaderEvalContext& c) { c.color                = c.coords.swizzle(0,1,2,3) + 0.5f*c.coords.swizzle(1,2,3,0); }
773
774 void evalSubscriptMat3x2        (ShaderEvalContext& c) { c.color.xy()   = c.coords.swizzle(0,1) + 0.5f*c.coords.swizzle(1,2) + 0.25f*c.coords.swizzle(2,3); }
775 void evalSubscriptMat3          (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(0,1,2) + 0.5f*c.coords.swizzle(1,2,3) + 0.25f*c.coords.swizzle(2,3,0); }
776 void evalSubscriptMat3x4        (ShaderEvalContext& c) { c.color                = c.coords.swizzle(0,1,2,3) + 0.5f*c.coords.swizzle(1,2,3,0) + 0.25f*c.coords.swizzle(2,3,0,1); }
777
778 void evalSubscriptMat4x2        (ShaderEvalContext& c) { c.color.xy()   = c.coords.swizzle(0,1) + 0.5f*c.coords.swizzle(1,2) + 0.25f*c.coords.swizzle(2,3) + 0.125f*c.coords.swizzle(3,0); }
779 void evalSubscriptMat4x3        (ShaderEvalContext& c) { c.color.xyz()  = c.coords.swizzle(0,1,2) + 0.5f*c.coords.swizzle(1,2,3) + 0.25f*c.coords.swizzle(2,3,0) + 0.125f*c.coords.swizzle(3,0,1); }
780 void evalSubscriptMat4          (ShaderEvalContext& c) { c.color                = c.coords + 0.5f*c.coords.swizzle(1,2,3,0) + 0.25f*c.coords.swizzle(2,3,0,1) + 0.125f*c.coords.swizzle(3,0,1,2); }
781
782 static ShaderEvalFunc getMatrixSubscriptEvalFunc (DataType dataType)
783 {
784         switch (dataType)
785         {
786                 case TYPE_FLOAT_MAT2:           return evalSubscriptMat2;
787                 case TYPE_FLOAT_MAT2X3:         return evalSubscriptMat2x3;
788                 case TYPE_FLOAT_MAT2X4:         return evalSubscriptMat2x4;
789                 case TYPE_FLOAT_MAT3X2:         return evalSubscriptMat3x2;
790                 case TYPE_FLOAT_MAT3:           return evalSubscriptMat3;
791                 case TYPE_FLOAT_MAT3X4:         return evalSubscriptMat3x4;
792                 case TYPE_FLOAT_MAT4X2:         return evalSubscriptMat4x2;
793                 case TYPE_FLOAT_MAT4X3:         return evalSubscriptMat4x3;
794                 case TYPE_FLOAT_MAT4:           return evalSubscriptMat4;
795
796                 default:
797                         DE_FATAL("Invalid data type.");
798                         return DE_NULL;
799         }
800 }
801
802 static ShaderIndexingCase* createMatrixSubscriptCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, IndexAccessType writeAccess, IndexAccessType readAccess)
803 {
804         std::ostringstream vtx;
805         std::ostringstream frag;
806         std::ostringstream& op = isVertexCase ? vtx : frag;
807
808         int                     numCols         = getDataTypeMatrixNumColumns(varType);
809         int                     numRows         = getDataTypeMatrixNumRows(varType);
810         const char*     matSizeName     = getIntUniformName(numCols);
811         DataType        vecType         = getDataTypeFloatVec(numRows);
812
813         vtx << "#version 300 es\n";
814         frag << "#version 300 es\n";
815
816         vtx << "in highp vec4 a_position;\n";
817         vtx << "in highp vec4 a_coords;\n";
818         frag << "layout(location = 0) out mediump vec4 o_color;\n";
819
820         if (isVertexCase)
821         {
822                 vtx << "out mediump vec4 v_color;\n";
823                 frag << "in mediump vec4 v_color;\n";
824         }
825         else
826         {
827                 vtx << "out mediump vec4 v_coords;\n";
828                 frag << "in mediump vec4 v_coords;\n";
829         }
830
831         if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC)
832         {
833                 op << "uniform mediump int ui_zero";
834                 if (numCols >= 2) op << ", ui_one";
835                 if (numCols >= 3) op << ", ui_two";
836                 if (numCols >= 4) op << ", ui_three";
837                 op << ";\n";
838         }
839
840         if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP)
841                 op << "uniform mediump int " << matSizeName << ";\n";
842
843         vtx << "\n";
844         vtx << "void main()\n";
845         vtx << "{\n";
846         vtx << "        gl_Position = a_position;\n";
847
848         frag << "\n";
849         frag << "void main()\n";
850         frag << "{\n";
851
852         // Write matrix.
853         if (isVertexCase)
854                 op << " ${PRECISION} vec4 coords = a_coords;\n";
855         else
856                 op << " ${PRECISION} vec4 coords = v_coords;\n";
857
858         op << " ${PRECISION} ${MAT_TYPE} tmp;\n";
859         if (writeAccess == INDEXACCESS_STATIC)
860         {
861                 op << " tmp[0] = ${VEC_TYPE}(coords);\n";
862                 if (numCols >= 2) op << "       tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n";
863                 if (numCols >= 3) op << "       tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n";
864                 if (numCols >= 4) op << "       tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n";
865         }
866         else if (writeAccess == INDEXACCESS_DYNAMIC)
867         {
868                 op << " tmp[ui_zero]  = ${VEC_TYPE}(coords);\n";
869                 if (numCols >= 2) op << "       tmp[ui_one]   = ${VEC_TYPE}(coords.yzwx) * 0.5;\n";
870                 if (numCols >= 3) op << "       tmp[ui_two]   = ${VEC_TYPE}(coords.zwxy) * 0.25;\n";
871                 if (numCols >= 4) op << "       tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n";
872         }
873         else if (writeAccess == INDEXACCESS_STATIC_LOOP)
874         {
875                 op << " for (int i = 0; i < " << numCols << "; i++)\n";
876                 op << " {\n";
877                 op << "         tmp[i] = ${VEC_TYPE}(coords);\n";
878                 op << "         coords = coords.yzwx * 0.5;\n";
879                 op << " }\n";
880         }
881         else
882         {
883                 DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP);
884                 op << " for (int i = 0; i < " << matSizeName << "; i++)\n";
885                 op << " {\n";
886                 op << "         tmp[i] = ${VEC_TYPE}(coords);\n";
887                 op << "         coords = coords.yzwx * 0.5;\n";
888                 op << " }\n";
889         }
890
891         // Read matrix.
892         op << " ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n";
893         if (readAccess == INDEXACCESS_STATIC)
894         {
895                 op << " res += tmp[0];\n";
896                 if (numCols >= 2) op << "       res += tmp[1];\n";
897                 if (numCols >= 3) op << "       res += tmp[2];\n";
898                 if (numCols >= 4) op << "       res += tmp[3];\n";
899         }
900         else if (readAccess == INDEXACCESS_DYNAMIC)
901         {
902                 op << " res += tmp[ui_zero];\n";
903                 if (numCols >= 2) op << "       res += tmp[ui_one];\n";
904                 if (numCols >= 3) op << "       res += tmp[ui_two];\n";
905                 if (numCols >= 4) op << "       res += tmp[ui_three];\n";
906         }
907         else if (readAccess == INDEXACCESS_STATIC_LOOP)
908         {
909                 op << " for (int i = 0; i < " << numCols << "; i++)\n";
910                 op << "         res += tmp[i];\n";
911         }
912         else
913         {
914                 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
915                 op << " for (int i = 0; i < " << matSizeName << "; i++)\n";
916                 op << "         res += tmp[i];\n";
917         }
918
919         if (isVertexCase)
920         {
921                 vtx << "        v_color = vec4(res${PADDING});\n";
922                 frag << "       o_color = v_color;\n";
923         }
924         else
925         {
926                 vtx << "        v_coords = a_coords;\n";
927                 frag << "       o_color = vec4(res${PADDING});\n";
928         }
929
930         vtx << "}\n";
931         frag << "}\n";
932
933         // Fill in shader templates.
934         map<string, string> params;
935         params.insert(pair<string, string>("MAT_TYPE", getDataTypeName(varType)));
936         params.insert(pair<string, string>("VEC_TYPE", getDataTypeName(vecType)));
937         params.insert(pair<string, string>("PRECISION", "mediump"));
938
939         if (numRows == 2)
940                 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
941         else if (numRows == 3)
942                 params.insert(pair<string, string>("PADDING", ", 1.0"));
943         else
944                 params.insert(pair<string, string>("PADDING", ""));
945
946         StringTemplate vertTemplate(vtx.str().c_str());
947         StringTemplate fragTemplate(frag.str().c_str());
948         string vertexShaderSource = vertTemplate.specialize(params);
949         string fragmentShaderSource = fragTemplate.specialize(params);
950
951         ShaderEvalFunc evalFunc = getMatrixSubscriptEvalFunc(varType);
952         return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str());
953 }
954
955 // ShaderIndexingTests.
956
957 ShaderIndexingTests::ShaderIndexingTests(Context& context)
958         : TestCaseGroup(context, "indexing", "Indexing Tests")
959 {
960 }
961
962 ShaderIndexingTests::~ShaderIndexingTests (void)
963 {
964 }
965
966 void ShaderIndexingTests::init (void)
967 {
968         static const ShaderType s_shaderTypes[] =
969         {
970                 SHADERTYPE_VERTEX,
971                 SHADERTYPE_FRAGMENT
972         };
973
974         static const DataType s_floatAndVecTypes[] =
975         {
976                 TYPE_FLOAT,
977                 TYPE_FLOAT_VEC2,
978                 TYPE_FLOAT_VEC3,
979                 TYPE_FLOAT_VEC4
980         };
981
982         // Varying array access cases.
983         {
984                 TestCaseGroup* varyingGroup = new TestCaseGroup(m_context, "varying_array", "Varying array access tests.");
985                 addChild(varyingGroup);
986
987                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
988                 {
989                         DataType varType = s_floatAndVecTypes[typeNdx];
990                         for (int vertAccess = 0; vertAccess < INDEXACCESS_LAST; vertAccess++)
991                         {
992                                 for (int fragAccess = 0; fragAccess < INDEXACCESS_LAST; fragAccess++)
993                                 {
994                                         const char* vertAccessName = getIndexAccessTypeName((IndexAccessType)vertAccess);
995                                         const char* fragAccessName = getIndexAccessTypeName((IndexAccessType)fragAccess);
996                                         string name = string(getDataTypeName(varType)) + "_" + vertAccessName + "_write_" + fragAccessName + "_read";
997                                         string desc = string("Varying array with ") + vertAccessName + " write in vertex shader and " + fragAccessName + " read in fragment shader.";
998                                         varyingGroup->addChild(createVaryingArrayCase(m_context, name.c_str(), desc.c_str(), varType, (IndexAccessType)vertAccess, (IndexAccessType)fragAccess));
999                                 }
1000                         }
1001                 }
1002         }
1003
1004         // Uniform array access cases.
1005         {
1006                 TestCaseGroup* uniformGroup = new TestCaseGroup(m_context, "uniform_array", "Uniform array access tests.");
1007                 addChild(uniformGroup);
1008
1009                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1010                 {
1011                         DataType varType = s_floatAndVecTypes[typeNdx];
1012                         for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1013                         {
1014                                 const char* readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1015                                 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1016                                 {
1017                                         ShaderType      shaderType              = s_shaderTypes[shaderTypeNdx];
1018                                         const char*     shaderTypeName  = getShaderTypeName(shaderType);
1019                                         string          name                    = string(getDataTypeName(varType)) + "_" + readAccessName + "_read_" + shaderTypeName;
1020                                         string          desc                    = string("Uniform array with ") + readAccessName + " read in " + shaderTypeName + " shader.";
1021                                         bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1022                                         uniformGroup->addChild(createUniformArrayCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (IndexAccessType)readAccess));
1023                                 }
1024                         }
1025                 }
1026         }
1027
1028         // Temporary array access cases.
1029         {
1030                 TestCaseGroup* tmpGroup = new TestCaseGroup(m_context, "tmp_array", "Temporary array access tests.");
1031                 addChild(tmpGroup);
1032
1033                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1034                 {
1035                         DataType varType = s_floatAndVecTypes[typeNdx];
1036                         for (int writeAccess = 0; writeAccess < INDEXACCESS_LAST; writeAccess++)
1037                         {
1038                                 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1039                                 {
1040                                         const char* writeAccessName = getIndexAccessTypeName((IndexAccessType)writeAccess);
1041                                         const char* readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1042
1043                                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1044                                         {
1045                                                 ShaderType      shaderType              = s_shaderTypes[shaderTypeNdx];
1046                                                 const char* shaderTypeName      = getShaderTypeName(shaderType);
1047                                                 string          name                    = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
1048                                                 string          desc                    = string("Temporary array with ") + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
1049                                                 bool            isVertexCase    = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1050                                                 tmpGroup->addChild(createTmpArrayCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (IndexAccessType)writeAccess, (IndexAccessType)readAccess));
1051                                         }
1052                                 }
1053                         }
1054                 }
1055         }
1056
1057         // Vector indexing with subscripts.
1058         {
1059                 TestCaseGroup* vecGroup = new TestCaseGroup(m_context, "vector_subscript", "Vector subscript indexing.");
1060                 addChild(vecGroup);
1061
1062                 static const DataType s_vectorTypes[] =
1063                 {
1064                         TYPE_FLOAT_VEC2,
1065                         TYPE_FLOAT_VEC3,
1066                         TYPE_FLOAT_VEC4
1067                 };
1068
1069                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_vectorTypes); typeNdx++)
1070                 {
1071                         DataType varType = s_vectorTypes[typeNdx];
1072                         for (int writeAccess = 0; writeAccess < VECTORACCESS_LAST; writeAccess++)
1073                         {
1074                                 for (int readAccess = 0; readAccess < VECTORACCESS_LAST; readAccess++)
1075                                 {
1076                                         const char* writeAccessName = getVectorAccessTypeName((VectorAccessType)writeAccess);
1077                                         const char* readAccessName = getVectorAccessTypeName((VectorAccessType)readAccess);
1078
1079                                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1080                                         {
1081                                                 ShaderType      shaderType              = s_shaderTypes[shaderTypeNdx];
1082                                                 const char* shaderTypeName      = getShaderTypeName(shaderType);
1083                                                 string          name                    = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
1084                                                 string          desc                    = string("Vector subscript access with ") + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
1085                                                 bool            isVertexCase    = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1086                                                 vecGroup->addChild(createVectorSubscriptCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (VectorAccessType)writeAccess, (VectorAccessType)readAccess));
1087                                         }
1088                                 }
1089                         }
1090                 }
1091         }
1092
1093         // Matrix indexing with subscripts.
1094         {
1095                 TestCaseGroup* matGroup = new TestCaseGroup(m_context, "matrix_subscript", "Matrix subscript indexing.");
1096                 addChild(matGroup);
1097
1098                 static const DataType s_matrixTypes[] =
1099                 {
1100                         TYPE_FLOAT_MAT2,
1101                         TYPE_FLOAT_MAT2X3,
1102                         TYPE_FLOAT_MAT2X4,
1103                         TYPE_FLOAT_MAT3X2,
1104                         TYPE_FLOAT_MAT3,
1105                         TYPE_FLOAT_MAT3X4,
1106                         TYPE_FLOAT_MAT4X2,
1107                         TYPE_FLOAT_MAT4X3,
1108                         TYPE_FLOAT_MAT4
1109                 };
1110
1111                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_matrixTypes); typeNdx++)
1112                 {
1113                         DataType varType = s_matrixTypes[typeNdx];
1114                         for (int writeAccess = 0; writeAccess < INDEXACCESS_LAST; writeAccess++)
1115                         {
1116                                 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1117                                 {
1118                                         const char* writeAccessName = getIndexAccessTypeName((IndexAccessType)writeAccess);
1119                                         const char* readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1120
1121                                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1122                                         {
1123                                                 ShaderType      shaderType              = s_shaderTypes[shaderTypeNdx];
1124                                                 const char* shaderTypeName      = getShaderTypeName(shaderType);
1125                                                 string          name                    = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName;
1126                                                 string          desc                    = string("Vector subscript access with ") + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader.";
1127                                                 bool            isVertexCase    = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1128                                                 matGroup->addChild(createMatrixSubscriptCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (IndexAccessType)writeAccess, (IndexAccessType)readAccess));
1129                                         }
1130                                 }
1131                         }
1132                 }
1133         }
1134 }
1135
1136 } // Functional
1137 } // gles3
1138 } // deqp