xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcShaderIndexingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 
getIndexAccessTypeName(IndexAccessType accessType)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 
getVectorAccessTypeName(VectorAccessType accessType)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 
evalArrayCoordsFloat(ShaderEvalContext & c)88 void evalArrayCoordsFloat(ShaderEvalContext &c)
89 {
90     c.color.x() = 1.875f * c.coords.x();
91 }
evalArrayCoordsVec2(ShaderEvalContext & c)92 void evalArrayCoordsVec2(ShaderEvalContext &c)
93 {
94     c.color.xy() = 1.875f * c.coords.swizzle(0, 1);
95 }
evalArrayCoordsVec3(ShaderEvalContext & c)96 void evalArrayCoordsVec3(ShaderEvalContext &c)
97 {
98     c.color.xyz() = 1.875f * c.coords.swizzle(0, 1, 2);
99 }
evalArrayCoordsVec4(ShaderEvalContext & c)100 void evalArrayCoordsVec4(ShaderEvalContext &c)
101 {
102     c.color = 1.875f * c.coords;
103 }
104 
getArrayCoordsEvalFunc(DataType dataType)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(false && "Invalid data type.");
117     return NULL;
118 }
119 
evalArrayUniformFloat(ShaderEvalContext & c)120 void evalArrayUniformFloat(ShaderEvalContext &c)
121 {
122     c.color.x() = 1.875f * c.constCoords.x();
123 }
evalArrayUniformVec2(ShaderEvalContext & c)124 void evalArrayUniformVec2(ShaderEvalContext &c)
125 {
126     c.color.xy() = 1.875f * c.constCoords.swizzle(0, 1);
127 }
evalArrayUniformVec3(ShaderEvalContext & c)128 void evalArrayUniformVec3(ShaderEvalContext &c)
129 {
130     c.color.xyz() = 1.875f * c.constCoords.swizzle(0, 1, 2);
131 }
evalArrayUniformVec4(ShaderEvalContext & c)132 void evalArrayUniformVec4(ShaderEvalContext &c)
133 {
134     c.color = 1.875f * c.constCoords;
135 }
136 
getArrayUniformEvalFunc(DataType dataType)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(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(uint32_t programID);
166     virtual void setupUniforms(uint32_t programID, const Vec4 &constCoords);
167 
168     DataType m_varType;
169 };
170 
ShaderIndexingCase(Context & context,const char * name,const char * description,bool isVertexCase,DataType varType,ShaderEvalFunc evalFunc,const char * vertShaderSource,const char * fragShaderSource)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 
~ShaderIndexingCase(void)182 ShaderIndexingCase::~ShaderIndexingCase(void)
183 {
184 }
185 
setup(uint32_t programID)186 void ShaderIndexingCase::setup(uint32_t programID)
187 {
188     DE_UNREF(programID);
189 }
190 
setupUniforms(uint32_t programID,const Vec4 & constCoords)191 void ShaderIndexingCase::setupUniforms(uint32_t 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 
createVaryingArrayCase(Context & context,const char * caseName,const char * description,glu::GLSLVersion glslVersion,DataType varType,IndexAccessType vertAccess,IndexAccessType fragAccess)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 
createUniformArrayCase(Context & context,const char * caseName,const char * description,glu::GLSLVersion glslVersion,bool isVertexCase,DataType varType,IndexAccessType readAccess)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 
createTmpArrayCase(Context & context,const char * caseName,const char * description,glu::GLSLVersion glslVersion,bool isVertexCase,DataType varType,IndexAccessType writeAccess,IndexAccessType readAccess)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 
evalGreenColor(ShaderEvalContext & c)627 void evalGreenColor(ShaderEvalContext &c)
628 {
629     c.color = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
630 }
631 
createTmpArrayVertexIdCase(Context & context,const char * caseName,const char * description,glu::GLSLVersion glslVersion)632 static ShaderIndexingCase *createTmpArrayVertexIdCase(Context &context, const char *caseName, const char *description,
633                                                       glu::GLSLVersion glslVersion)
634 {
635     DE_ASSERT(glslVersion == glu::GLSL_VERSION_300_ES || glslVersion == glu::GLSL_VERSION_310_ES ||
636               glslVersion >= glu::GLSL_VERSION_330);
637 
638     std::string vtx =
639         glu::getGLSLVersionDeclaration(glslVersion) + std::string("\n"
640                                                                   "precision highp float;\n"
641                                                                   "in vec4 a_position;\n"
642                                                                   "out float color[4];\n"
643                                                                   "void main()\n"
644                                                                   "{\n"
645                                                                   "    for(int i = 0; i < 4; i++)\n"
646                                                                   "    {\n"
647                                                                   "        int j = (gl_VertexID + i) % 4;\n"
648                                                                   "        color[j] = (j % 2 == 0) ? 0.0 : 1.0;\n"
649                                                                   "    }\n"
650                                                                   "    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
651                                                                   "}\n");
652 
653     std::string frag = glu::getGLSLVersionDeclaration(glslVersion) +
654                        std::string("\n"
655                                    "precision highp float;\n"
656                                    "in float color[4];\n"
657                                    "layout(location = 0) out vec4 o_color;\n"
658                                    "void main()\n"
659                                    "{\n"
660                                    "    float temp[4];\n"
661                                    "    for(int i = 0; i < 4; i++)\n"
662                                    "    {\n"
663                                    "        temp[i] = color[i];\n"
664                                    "        o_color = vec4(temp[0], temp[1], temp[2], temp[3]);\n"
665                                    "    }\n"
666                                    "}\n");
667 
668     return new ShaderIndexingCase(context, caseName, description, false, TYPE_FLOAT, evalGreenColor, vtx.c_str(),
669                                   frag.c_str());
670 }
671 
672 // VECTOR SUBSCRIPT.
673 
evalSubscriptVec2(ShaderEvalContext & c)674 void evalSubscriptVec2(ShaderEvalContext &c)
675 {
676     c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y());
677 }
evalSubscriptVec3(ShaderEvalContext & c)678 void evalSubscriptVec3(ShaderEvalContext &c)
679 {
680     c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y() + 0.25f * c.coords.z());
681 }
evalSubscriptVec4(ShaderEvalContext & c)682 void evalSubscriptVec4(ShaderEvalContext &c)
683 {
684     c.color.xyz() = Vec3(c.coords.x() + 0.5f * c.coords.y() + 0.25f * c.coords.z() + 0.125f * c.coords.w());
685 }
686 
getVectorSubscriptEvalFunc(DataType dataType)687 static ShaderEvalFunc getVectorSubscriptEvalFunc(DataType dataType)
688 {
689     if (dataType == TYPE_FLOAT_VEC2)
690         return evalSubscriptVec2;
691     else if (dataType == TYPE_FLOAT_VEC3)
692         return evalSubscriptVec3;
693     else if (dataType == TYPE_FLOAT_VEC4)
694         return evalSubscriptVec4;
695 
696     DE_ASSERT(false && "Invalid data type.");
697     return NULL;
698 }
699 
createVectorSubscriptCase(Context & context,const char * caseName,const char * description,glu::GLSLVersion glslVersion,bool isVertexCase,DataType varType,VectorAccessType writeAccess,VectorAccessType readAccess)700 static ShaderIndexingCase *createVectorSubscriptCase(Context &context, const char *caseName, const char *description,
701                                                      glu::GLSLVersion glslVersion, bool isVertexCase, DataType varType,
702                                                      VectorAccessType writeAccess, VectorAccessType readAccess)
703 {
704     std::ostringstream vtx;
705     std::ostringstream frag;
706     std::ostringstream &op = isVertexCase ? vtx : frag;
707 
708     int vecLen             = getDataTypeScalarSize(varType);
709     const char *vecLenName = getIntUniformName(vecLen);
710 
711     vtx << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
712     frag << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
713 
714     vtx << "in highp vec4 a_position;\n";
715     vtx << "in highp vec4 a_coords;\n";
716     frag << "layout(location = 0) out mediump vec4 o_color;\n";
717 
718     if (isVertexCase)
719     {
720         vtx << "out mediump vec3 v_color;\n";
721         frag << "in mediump vec3 v_color;\n";
722     }
723     else
724     {
725         vtx << "out mediump vec4 v_coords;\n";
726         frag << "in mediump vec4 v_coords;\n";
727     }
728 
729     if (writeAccess == SUBSCRIPT_DYNAMIC || readAccess == SUBSCRIPT_DYNAMIC)
730     {
731         op << "uniform mediump int ui_zero";
732         if (vecLen >= 2)
733             op << ", ui_one";
734         if (vecLen >= 3)
735             op << ", ui_two";
736         if (vecLen >= 4)
737             op << ", ui_three";
738         op << ";\n";
739     }
740 
741     if (writeAccess == SUBSCRIPT_DYNAMIC_LOOP || readAccess == SUBSCRIPT_DYNAMIC_LOOP)
742         op << "uniform mediump int " << vecLenName << ";\n";
743 
744     vtx << "\n";
745     vtx << "void main()\n";
746     vtx << "{\n";
747     vtx << "    gl_Position = a_position;\n";
748 
749     frag << "\n";
750     frag << "void main()\n";
751     frag << "{\n";
752 
753     // Write vector.
754     if (isVertexCase)
755         op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n";
756     else
757         op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n";
758 
759     op << " ${PRECISION} ${VAR_TYPE} tmp;\n";
760     if (writeAccess == DIRECT)
761         op << " tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n";
762     else if (writeAccess == COMPONENT)
763     {
764         op << " tmp.x = coords.x;\n";
765         if (vecLen >= 2)
766             op << "    tmp.y = coords.y * 0.5;\n";
767         if (vecLen >= 3)
768             op << "    tmp.z = coords.z * 0.25;\n";
769         if (vecLen >= 4)
770             op << "    tmp.w = coords.w * 0.125;\n";
771     }
772     else if (writeAccess == SUBSCRIPT_STATIC)
773     {
774         op << " tmp[0] = coords.x;\n";
775         if (vecLen >= 2)
776             op << "    tmp[1] = coords.y * 0.5;\n";
777         if (vecLen >= 3)
778             op << "    tmp[2] = coords.z * 0.25;\n";
779         if (vecLen >= 4)
780             op << "    tmp[3] = coords.w * 0.125;\n";
781     }
782     else if (writeAccess == SUBSCRIPT_DYNAMIC)
783     {
784         op << " tmp[ui_zero]  = coords.x;\n";
785         if (vecLen >= 2)
786             op << "    tmp[ui_one]   = coords.y * 0.5;\n";
787         if (vecLen >= 3)
788             op << "    tmp[ui_two]   = coords.z * 0.25;\n";
789         if (vecLen >= 4)
790             op << "    tmp[ui_three] = coords.w * 0.125;\n";
791     }
792     else if (writeAccess == SUBSCRIPT_STATIC_LOOP)
793     {
794         op << " for (int i = 0; i < " << vecLen << "; i++)\n";
795         op << " {\n";
796         op << "     tmp[i] = coords.x;\n";
797         op << "     coords = coords.${ROT_SWIZZLE} * 0.5;\n";
798         op << " }\n";
799     }
800     else
801     {
802         DE_ASSERT(writeAccess == SUBSCRIPT_DYNAMIC_LOOP);
803         op << " for (int i = 0; i < " << vecLenName << "; i++)\n";
804         op << " {\n";
805         op << "     tmp[i] = coords.x;\n";
806         op << "     coords = coords.${ROT_SWIZZLE} * 0.5;\n";
807         op << " }\n";
808     }
809 
810     // Read vector.
811     op << " ${PRECISION} float res = 0.0;\n";
812     if (readAccess == DIRECT)
813         op << " res = dot(tmp, ${VAR_TYPE}(1.0));\n";
814     else if (readAccess == COMPONENT)
815     {
816         op << " res += tmp.x;\n";
817         if (vecLen >= 2)
818             op << "    res += tmp.y;\n";
819         if (vecLen >= 3)
820             op << "    res += tmp.z;\n";
821         if (vecLen >= 4)
822             op << "    res += tmp.w;\n";
823     }
824     else if (readAccess == SUBSCRIPT_STATIC)
825     {
826         op << " res += tmp[0];\n";
827         if (vecLen >= 2)
828             op << "    res += tmp[1];\n";
829         if (vecLen >= 3)
830             op << "    res += tmp[2];\n";
831         if (vecLen >= 4)
832             op << "    res += tmp[3];\n";
833     }
834     else if (readAccess == SUBSCRIPT_DYNAMIC)
835     {
836         op << " res += tmp[ui_zero];\n";
837         if (vecLen >= 2)
838             op << "    res += tmp[ui_one];\n";
839         if (vecLen >= 3)
840             op << "    res += tmp[ui_two];\n";
841         if (vecLen >= 4)
842             op << "    res += tmp[ui_three];\n";
843     }
844     else if (readAccess == SUBSCRIPT_STATIC_LOOP)
845     {
846         op << " for (int i = 0; i < " << vecLen << "; i++)\n";
847         op << "     res += tmp[i];\n";
848     }
849     else
850     {
851         DE_ASSERT(readAccess == SUBSCRIPT_DYNAMIC_LOOP);
852         op << " for (int i = 0; i < " << vecLenName << "; i++)\n";
853         op << "     res += tmp[i];\n";
854     }
855 
856     if (isVertexCase)
857     {
858         vtx << "    v_color = vec3(res);\n";
859         frag << "   o_color = vec4(v_color.rgb, 1.0);\n";
860     }
861     else
862     {
863         vtx << "    v_coords = a_coords;\n";
864         frag << "   o_color = vec4(vec3(res), 1.0);\n";
865     }
866 
867     vtx << "}\n";
868     frag << "}\n";
869 
870     // Fill in shader templates.
871     static const char *s_swizzles[5]    = {"", "x", "xy", "xyz", "xyzw"};
872     static const char *s_rotSwizzles[5] = {"", "x", "yx", "yzx", "yzwx"};
873 
874     map<string, string> params;
875     params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType)));
876     params.insert(pair<string, string>("PRECISION", "mediump"));
877     params.insert(pair<string, string>("SWIZZLE", s_swizzles[vecLen]));
878     params.insert(pair<string, string>("ROT_SWIZZLE", s_rotSwizzles[vecLen]));
879 
880     StringTemplate vertTemplate(vtx.str().c_str());
881     StringTemplate fragTemplate(frag.str().c_str());
882     string vertexShaderSource   = vertTemplate.specialize(params);
883     string fragmentShaderSource = fragTemplate.specialize(params);
884 
885     ShaderEvalFunc evalFunc = getVectorSubscriptEvalFunc(varType);
886     return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc,
887                                   vertexShaderSource.c_str(), fragmentShaderSource.c_str());
888 }
889 
890 // MATRIX SUBSCRIPT.
891 
evalSubscriptMat2(ShaderEvalContext & c)892 void evalSubscriptMat2(ShaderEvalContext &c)
893 {
894     c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2);
895 }
evalSubscriptMat2x3(ShaderEvalContext & c)896 void evalSubscriptMat2x3(ShaderEvalContext &c)
897 {
898     c.color.xyz() = c.coords.swizzle(0, 1, 2) + 0.5f * c.coords.swizzle(1, 2, 3);
899 }
evalSubscriptMat2x4(ShaderEvalContext & c)900 void evalSubscriptMat2x4(ShaderEvalContext &c)
901 {
902     c.color = c.coords.swizzle(0, 1, 2, 3) + 0.5f * c.coords.swizzle(1, 2, 3, 0);
903 }
904 
evalSubscriptMat3x2(ShaderEvalContext & c)905 void evalSubscriptMat3x2(ShaderEvalContext &c)
906 {
907     c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2) + 0.25f * c.coords.swizzle(2, 3);
908 }
evalSubscriptMat3(ShaderEvalContext & c)909 void evalSubscriptMat3(ShaderEvalContext &c)
910 {
911     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);
912 }
evalSubscriptMat3x4(ShaderEvalContext & c)913 void evalSubscriptMat3x4(ShaderEvalContext &c)
914 {
915     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);
916 }
917 
evalSubscriptMat4x2(ShaderEvalContext & c)918 void evalSubscriptMat4x2(ShaderEvalContext &c)
919 {
920     c.color.xy() = c.coords.swizzle(0, 1) + 0.5f * c.coords.swizzle(1, 2) + 0.25f * c.coords.swizzle(2, 3) +
921                    0.125f * c.coords.swizzle(3, 0);
922 }
evalSubscriptMat4x3(ShaderEvalContext & c)923 void evalSubscriptMat4x3(ShaderEvalContext &c)
924 {
925     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) +
926                     0.125f * c.coords.swizzle(3, 0, 1);
927 }
evalSubscriptMat4(ShaderEvalContext & c)928 void evalSubscriptMat4(ShaderEvalContext &c)
929 {
930     c.color = c.coords + 0.5f * c.coords.swizzle(1, 2, 3, 0) + 0.25f * c.coords.swizzle(2, 3, 0, 1) +
931               0.125f * c.coords.swizzle(3, 0, 1, 2);
932 }
933 
getMatrixSubscriptEvalFunc(DataType dataType)934 static ShaderEvalFunc getMatrixSubscriptEvalFunc(DataType dataType)
935 {
936     switch (dataType)
937     {
938     case TYPE_FLOAT_MAT2:
939         return evalSubscriptMat2;
940     case TYPE_FLOAT_MAT2X3:
941         return evalSubscriptMat2x3;
942     case TYPE_FLOAT_MAT2X4:
943         return evalSubscriptMat2x4;
944     case TYPE_FLOAT_MAT3X2:
945         return evalSubscriptMat3x2;
946     case TYPE_FLOAT_MAT3:
947         return evalSubscriptMat3;
948     case TYPE_FLOAT_MAT3X4:
949         return evalSubscriptMat3x4;
950     case TYPE_FLOAT_MAT4X2:
951         return evalSubscriptMat4x2;
952     case TYPE_FLOAT_MAT4X3:
953         return evalSubscriptMat4x3;
954     case TYPE_FLOAT_MAT4:
955         return evalSubscriptMat4;
956 
957     default:
958         DE_ASSERT(false && "Invalid data type.");
959         return DE_NULL;
960     }
961 }
962 
createMatrixSubscriptCase(Context & context,const char * caseName,const char * description,glu::GLSLVersion glslVersion,bool isVertexCase,DataType varType,IndexAccessType writeAccess,IndexAccessType readAccess)963 static ShaderIndexingCase *createMatrixSubscriptCase(Context &context, const char *caseName, const char *description,
964                                                      glu::GLSLVersion glslVersion, bool isVertexCase, DataType varType,
965                                                      IndexAccessType writeAccess, IndexAccessType readAccess)
966 {
967     DE_ASSERT(glslVersion == glu::GLSL_VERSION_300_ES || glslVersion == glu::GLSL_VERSION_310_ES ||
968               glslVersion >= glu::GLSL_VERSION_330);
969 
970     std::ostringstream vtx;
971     std::ostringstream frag;
972     std::ostringstream &op = isVertexCase ? vtx : frag;
973 
974     int numCols             = getDataTypeMatrixNumColumns(varType);
975     int numRows             = getDataTypeMatrixNumRows(varType);
976     const char *matSizeName = getIntUniformName(numCols);
977     DataType vecType        = getDataTypeFloatVec(numRows);
978 
979     vtx << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
980     frag << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
981 
982     vtx << "in highp vec4 a_position;\n";
983     vtx << "in highp vec4 a_coords;\n";
984     frag << "layout(location = 0) out mediump vec4 o_color;\n";
985 
986     if (isVertexCase)
987     {
988         vtx << "out mediump vec4 v_color;\n";
989         frag << "in mediump vec4 v_color;\n";
990     }
991     else
992     {
993         vtx << "out mediump vec4 v_coords;\n";
994         frag << "in mediump vec4 v_coords;\n";
995     }
996 
997     if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC)
998     {
999         op << "uniform mediump int ui_zero";
1000         if (numCols >= 2)
1001             op << ", ui_one";
1002         if (numCols >= 3)
1003             op << ", ui_two";
1004         if (numCols >= 4)
1005             op << ", ui_three";
1006         op << ";\n";
1007     }
1008 
1009     if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP)
1010         op << "uniform mediump int " << matSizeName << ";\n";
1011 
1012     vtx << "\n";
1013     vtx << "void main()\n";
1014     vtx << "{\n";
1015     vtx << "    gl_Position = a_position;\n";
1016 
1017     frag << "\n";
1018     frag << "void main()\n";
1019     frag << "{\n";
1020 
1021     // Write matrix.
1022     if (isVertexCase)
1023         op << " ${PRECISION} vec4 coords = a_coords;\n";
1024     else
1025         op << " ${PRECISION} vec4 coords = v_coords;\n";
1026 
1027     op << " ${PRECISION} ${MAT_TYPE} tmp;\n";
1028     if (writeAccess == INDEXACCESS_STATIC)
1029     {
1030         op << " tmp[0] = ${VEC_TYPE}(coords);\n";
1031         if (numCols >= 2)
1032             op << "   tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n";
1033         if (numCols >= 3)
1034             op << "   tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n";
1035         if (numCols >= 4)
1036             op << "   tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n";
1037     }
1038     else if (writeAccess == INDEXACCESS_DYNAMIC)
1039     {
1040         op << " tmp[ui_zero]  = ${VEC_TYPE}(coords);\n";
1041         if (numCols >= 2)
1042             op << "   tmp[ui_one]   = ${VEC_TYPE}(coords.yzwx) * 0.5;\n";
1043         if (numCols >= 3)
1044             op << "   tmp[ui_two]   = ${VEC_TYPE}(coords.zwxy) * 0.25;\n";
1045         if (numCols >= 4)
1046             op << "   tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n";
1047     }
1048     else if (writeAccess == INDEXACCESS_STATIC_LOOP)
1049     {
1050         op << " for (int i = 0; i < " << numCols << "; i++)\n";
1051         op << " {\n";
1052         op << "     tmp[i] = ${VEC_TYPE}(coords);\n";
1053         op << "     coords = coords.yzwx * 0.5;\n";
1054         op << " }\n";
1055     }
1056     else
1057     {
1058         DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP);
1059         op << " for (int i = 0; i < " << matSizeName << "; i++)\n";
1060         op << " {\n";
1061         op << "     tmp[i] = ${VEC_TYPE}(coords);\n";
1062         op << "     coords = coords.yzwx * 0.5;\n";
1063         op << " }\n";
1064     }
1065 
1066     // Read matrix.
1067     op << " ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n";
1068     if (readAccess == INDEXACCESS_STATIC)
1069     {
1070         op << " res += tmp[0];\n";
1071         if (numCols >= 2)
1072             op << "   res += tmp[1];\n";
1073         if (numCols >= 3)
1074             op << "   res += tmp[2];\n";
1075         if (numCols >= 4)
1076             op << "   res += tmp[3];\n";
1077     }
1078     else if (readAccess == INDEXACCESS_DYNAMIC)
1079     {
1080         op << " res += tmp[ui_zero];\n";
1081         if (numCols >= 2)
1082             op << "   res += tmp[ui_one];\n";
1083         if (numCols >= 3)
1084             op << "   res += tmp[ui_two];\n";
1085         if (numCols >= 4)
1086             op << "   res += tmp[ui_three];\n";
1087     }
1088     else if (readAccess == INDEXACCESS_STATIC_LOOP)
1089     {
1090         op << " for (int i = 0; i < " << numCols << "; i++)\n";
1091         op << "     res += tmp[i];\n";
1092     }
1093     else
1094     {
1095         DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP);
1096         op << " for (int i = 0; i < " << matSizeName << "; i++)\n";
1097         op << "     res += tmp[i];\n";
1098     }
1099 
1100     if (isVertexCase)
1101     {
1102         vtx << "    v_color = vec4(res${PADDING});\n";
1103         frag << "   o_color = v_color;\n";
1104     }
1105     else
1106     {
1107         vtx << "    v_coords = a_coords;\n";
1108         frag << "   o_color = vec4(res${PADDING});\n";
1109     }
1110 
1111     vtx << "}\n";
1112     frag << "}\n";
1113 
1114     // Fill in shader templates.
1115     map<string, string> params;
1116     params.insert(pair<string, string>("MAT_TYPE", getDataTypeName(varType)));
1117     params.insert(pair<string, string>("VEC_TYPE", getDataTypeName(vecType)));
1118     params.insert(pair<string, string>("PRECISION", "mediump"));
1119 
1120     if (numRows == 2)
1121         params.insert(pair<string, string>("PADDING", ", 0.0, 1.0"));
1122     else if (numRows == 3)
1123         params.insert(pair<string, string>("PADDING", ", 1.0"));
1124     else
1125         params.insert(pair<string, string>("PADDING", ""));
1126 
1127     StringTemplate vertTemplate(vtx.str().c_str());
1128     StringTemplate fragTemplate(frag.str().c_str());
1129     string vertexShaderSource   = vertTemplate.specialize(params);
1130     string fragmentShaderSource = fragTemplate.specialize(params);
1131 
1132     ShaderEvalFunc evalFunc = getMatrixSubscriptEvalFunc(varType);
1133     return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc,
1134                                   vertexShaderSource.c_str(), fragmentShaderSource.c_str());
1135 }
1136 
1137 // ShaderIndexingTests.
1138 
ShaderIndexingTests(Context & context,glu::GLSLVersion glslVersion)1139 ShaderIndexingTests::ShaderIndexingTests(Context &context, glu::GLSLVersion glslVersion)
1140     : TestCaseGroup(context, "indexing", "Indexing Tests")
1141     , m_glslVersion(glslVersion)
1142 {
1143 }
1144 
~ShaderIndexingTests(void)1145 ShaderIndexingTests::~ShaderIndexingTests(void)
1146 {
1147 }
1148 
init(void)1149 void ShaderIndexingTests::init(void)
1150 {
1151     static const DataType s_floatAndVecTypes[] = {TYPE_FLOAT, TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
1152 
1153     static const ShaderType s_shaderTypes[] = {SHADERTYPE_VERTEX, SHADERTYPE_FRAGMENT};
1154 
1155     // Varying array access cases.
1156     {
1157         TestCaseGroup *varyingGroup = new TestCaseGroup(m_context, "varying_array", "Varying array access tests.");
1158         addChild(varyingGroup);
1159 
1160         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1161         {
1162             DataType varType = s_floatAndVecTypes[typeNdx];
1163             for (int vertAccess = 0; vertAccess < INDEXACCESS_LAST; vertAccess++)
1164             {
1165                 for (int fragAccess = 0; fragAccess < INDEXACCESS_LAST; fragAccess++)
1166                 {
1167                     if (vertAccess == INDEXACCESS_STATIC && fragAccess == INDEXACCESS_STATIC)
1168                         continue;
1169 
1170                     const char *vertAccessName = getIndexAccessTypeName((IndexAccessType)vertAccess);
1171                     const char *fragAccessName = getIndexAccessTypeName((IndexAccessType)fragAccess);
1172                     string name =
1173                         string(getDataTypeName(varType)) + "_" + vertAccessName + "_write_" + fragAccessName + "_read";
1174                     string desc = string("Varying array with ") + vertAccessName + " write in vertex shader and " +
1175                                   fragAccessName + " read in fragment shader.";
1176                     varyingGroup->addChild(createVaryingArrayCase(m_context, name.c_str(), desc.c_str(), m_glslVersion,
1177                                                                   varType, (IndexAccessType)vertAccess,
1178                                                                   (IndexAccessType)fragAccess));
1179                 }
1180             }
1181         }
1182     }
1183 
1184     // Uniform array access cases.
1185     {
1186         TestCaseGroup *uniformGroup = new TestCaseGroup(m_context, "uniform_array", "Uniform array access tests.");
1187         addChild(uniformGroup);
1188 
1189         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1190         {
1191             DataType varType = s_floatAndVecTypes[typeNdx];
1192             for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++)
1193             {
1194                 const char *readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess);
1195                 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1196                 {
1197                     ShaderType shaderType      = s_shaderTypes[shaderTypeNdx];
1198                     const char *shaderTypeName = getShaderTypeName((ShaderType)shaderType);
1199                     string name = string(getDataTypeName(varType)) + "_" + readAccessName + "_read_" + shaderTypeName;
1200                     string desc =
1201                         string("Uniform array with ") + readAccessName + " read in " + shaderTypeName + " shader.";
1202                     bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1203                     uniformGroup->addChild(createUniformArrayCase(m_context, name.c_str(), desc.c_str(), m_glslVersion,
1204                                                                   isVertexCase, varType, (IndexAccessType)readAccess));
1205                 }
1206             }
1207         }
1208     }
1209 
1210     // Temporary array access cases.
1211     {
1212         TestCaseGroup *tmpGroup = new TestCaseGroup(m_context, "tmp_array", "Temporary array access tests.");
1213         addChild(tmpGroup);
1214 
1215         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++)
1216         {
1217             DataType varType = s_floatAndVecTypes[typeNdx];
1218             for (int isReadStatic = 0; isReadStatic < 2; isReadStatic++)
1219             {
1220                 for (int access = INDEXACCESS_STATIC + 1; access < INDEXACCESS_LAST; access++)
1221                 {
1222                     IndexAccessType readAccess  = isReadStatic ? INDEXACCESS_STATIC : (IndexAccessType)access;
1223                     IndexAccessType writeAccess = isReadStatic ? (IndexAccessType)access : INDEXACCESS_STATIC;
1224 
1225                     const char *writeAccessName = getIndexAccessTypeName(writeAccess);
1226                     const char *readAccessName  = getIndexAccessTypeName(readAccess);
1227 
1228                     for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1229                     {
1230                         ShaderType shaderType      = s_shaderTypes[shaderTypeNdx];
1231                         const char *shaderTypeName = getShaderTypeName((ShaderType)shaderType);
1232                         string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" +
1233                                       readAccessName + "_read_" + shaderTypeName;
1234                         string desc = string("Temporary array with ") + writeAccessName + " write and " +
1235                                       readAccessName + " read in " + shaderTypeName + " shader.";
1236                         bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1237                         tmpGroup->addChild(createTmpArrayCase(m_context, name.c_str(), desc.c_str(), m_glslVersion,
1238                                                               isVertexCase, varType, (IndexAccessType)writeAccess,
1239                                                               (IndexAccessType)readAccess));
1240                     }
1241                 }
1242             }
1243         }
1244 
1245         tmpGroup->addChild(createTmpArrayVertexIdCase(m_context, "vertexid", "", m_glslVersion));
1246     }
1247 
1248     // Vector indexing with subscripts.
1249     {
1250         TestCaseGroup *vecGroup = new TestCaseGroup(m_context, "vector_subscript", "Vector subscript indexing.");
1251         addChild(vecGroup);
1252 
1253         static const DataType s_vectorTypes[] = {TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
1254 
1255         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_vectorTypes); typeNdx++)
1256         {
1257             DataType varType = s_vectorTypes[typeNdx];
1258             for (int isReadDirect = 0; isReadDirect < 2; isReadDirect++)
1259             {
1260                 for (int access = SUBSCRIPT_STATIC; access < VECTORACCESS_LAST; access++)
1261                 {
1262                     VectorAccessType readAccess  = isReadDirect ? DIRECT : (VectorAccessType)access;
1263                     VectorAccessType writeAccess = isReadDirect ? (VectorAccessType)access : DIRECT;
1264 
1265                     const char *writeAccessName = getVectorAccessTypeName(writeAccess);
1266                     const char *readAccessName  = getVectorAccessTypeName(readAccess);
1267 
1268                     for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1269                     {
1270                         ShaderType shaderType      = s_shaderTypes[shaderTypeNdx];
1271                         const char *shaderTypeName = getShaderTypeName((ShaderType)shaderType);
1272                         string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" +
1273                                       readAccessName + "_read_" + shaderTypeName;
1274                         string desc = string("Vector subscript access with ") + writeAccessName + " write and " +
1275                                       readAccessName + " read in " + shaderTypeName + " shader.";
1276                         bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1277                         vecGroup->addChild(createVectorSubscriptCase(
1278                             m_context, name.c_str(), desc.c_str(), m_glslVersion, isVertexCase, varType,
1279                             (VectorAccessType)writeAccess, (VectorAccessType)readAccess));
1280                     }
1281                 }
1282             }
1283         }
1284     }
1285 
1286     // Matrix indexing with subscripts.
1287     {
1288         TestCaseGroup *matGroup = new TestCaseGroup(m_context, "matrix_subscript", "Matrix subscript indexing.");
1289         addChild(matGroup);
1290 
1291         static const DataType s_matrixTypes[] = {TYPE_FLOAT_MAT2,   TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2X4,
1292                                                  TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3,   TYPE_FLOAT_MAT3X4,
1293                                                  TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4};
1294 
1295         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_matrixTypes); typeNdx++)
1296         {
1297             DataType varType = s_matrixTypes[typeNdx];
1298             for (int isReadStatic = 0; isReadStatic < 2; isReadStatic++)
1299             {
1300                 for (int access = INDEXACCESS_STATIC + 1; access < INDEXACCESS_LAST; access++)
1301                 {
1302                     IndexAccessType readAccess  = isReadStatic ? INDEXACCESS_STATIC : (IndexAccessType)access;
1303                     IndexAccessType writeAccess = isReadStatic ? (IndexAccessType)access : INDEXACCESS_STATIC;
1304 
1305                     const char *writeAccessName = getIndexAccessTypeName(writeAccess);
1306                     const char *readAccessName  = getIndexAccessTypeName(readAccess);
1307 
1308                     for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1309                     {
1310                         ShaderType shaderType      = s_shaderTypes[shaderTypeNdx];
1311                         const char *shaderTypeName = getShaderTypeName((ShaderType)shaderType);
1312                         string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" +
1313                                       readAccessName + "_read_" + shaderTypeName;
1314                         string desc = string("Vector subscript access with ") + writeAccessName + " write and " +
1315                                       readAccessName + " read in " + shaderTypeName + " shader.";
1316                         bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX);
1317                         matGroup->addChild(createMatrixSubscriptCase(
1318                             m_context, name.c_str(), desc.c_str(), m_glslVersion, isVertexCase, varType,
1319                             (IndexAccessType)writeAccess, (IndexAccessType)readAccess));
1320                     }
1321                 }
1322             }
1323         }
1324     }
1325 }
1326 
1327 } // namespace deqp
1328