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