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