xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcShaderStructTests.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 struct tests.
23  */ /*-------------------------------------------------------------------*/
24 
25 #include "glcShaderStructTests.hpp"
26 #include "glcShaderRenderCase.hpp"
27 #include "gluTexture.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuStringTemplate.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "deMath.h"
33 
34 using tcu::StringTemplate;
35 
36 using std::ostringstream;
37 using std::string;
38 using std::vector;
39 
40 using namespace glu;
41 
42 namespace deqp
43 {
44 
45 enum
46 {
47     TEXTURE_GRADIENT = 0 //!< Unit index for gradient texture
48 };
49 
50 typedef void (*SetupUniformsFunc)(const glw::Functions &gl, uint32_t programID, const tcu::Vec4 &constCoords);
51 
52 class ShaderStructCase : public ShaderRenderCase
53 {
54 public:
55     ShaderStructCase(Context &context, const char *name, const char *description, bool isVertexCase, bool usesTextures,
56                      ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char *vertShaderSource,
57                      const char *fragShaderSource);
58     ~ShaderStructCase(void);
59 
60     void init(void);
61     void deinit(void);
62 
63     virtual void setupUniforms(uint32_t programID, const tcu::Vec4 &constCoords);
64 
65 private:
66     ShaderStructCase(const ShaderStructCase &);
67     ShaderStructCase &operator=(const ShaderStructCase &);
68 
69     SetupUniformsFunc m_setupUniforms;
70     bool m_usesTexture;
71 
72     glu::Texture2D *m_gradientTexture;
73 };
74 
ShaderStructCase(Context & context,const char * name,const char * description,bool isVertexCase,bool usesTextures,ShaderEvalFunc evalFunc,SetupUniformsFunc setupUniformsFunc,const char * vertShaderSource,const char * fragShaderSource)75 ShaderStructCase::ShaderStructCase(Context &context, const char *name, const char *description, bool isVertexCase,
76                                    bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc,
77                                    const char *vertShaderSource, const char *fragShaderSource)
78     : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
79                        description, isVertexCase, evalFunc)
80     , m_setupUniforms(setupUniformsFunc)
81     , m_usesTexture(usesTextures)
82     , m_gradientTexture(DE_NULL)
83 {
84     m_vertShaderSource = vertShaderSource;
85     m_fragShaderSource = fragShaderSource;
86 }
87 
~ShaderStructCase(void)88 ShaderStructCase::~ShaderStructCase(void)
89 {
90 }
91 
init(void)92 void ShaderStructCase::init(void)
93 {
94     if (m_usesTexture)
95     {
96         m_gradientTexture = new glu::Texture2D(m_renderCtx, GL_RGBA8, 128, 128);
97 
98         m_gradientTexture->getRefTexture().allocLevel(0);
99         tcu::fillWithComponentGradients(m_gradientTexture->getRefTexture().getLevel(0), tcu::Vec4(0.0f),
100                                         tcu::Vec4(1.0f));
101         m_gradientTexture->upload();
102 
103         m_textures.push_back(TextureBinding(
104             m_gradientTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
105                                             tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR)));
106         DE_ASSERT(m_textures.size() == 1);
107     }
108     ShaderRenderCase::init();
109 }
110 
deinit(void)111 void ShaderStructCase::deinit(void)
112 {
113     if (m_usesTexture)
114     {
115         delete m_gradientTexture;
116     }
117     ShaderRenderCase::deinit();
118 }
119 
setupUniforms(uint32_t programID,const tcu::Vec4 & constCoords)120 void ShaderStructCase::setupUniforms(uint32_t programID, const tcu::Vec4 &constCoords)
121 {
122     ShaderRenderCase::setupUniforms(programID, constCoords);
123     if (m_setupUniforms)
124         m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
125 }
126 
createStructCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion,bool isVertexCase,bool usesTextures,ShaderEvalFunc evalFunc,SetupUniformsFunc setupUniforms,const LineStream & shaderSrc)127 static ShaderStructCase *createStructCase(Context &context, const char *name, const char *description,
128                                           glu::GLSLVersion glslVersion, bool isVertexCase, bool usesTextures,
129                                           ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms,
130                                           const LineStream &shaderSrc)
131 {
132     const std::string versionDecl = glu::getGLSLVersionDeclaration(glslVersion);
133 
134     const std::string defaultVertSrc = versionDecl + "\n"
135                                                      "in highp vec4 a_position;\n"
136                                                      "in highp vec4 a_coords;\n"
137                                                      "out mediump vec4 v_coords;\n\n"
138                                                      "void main (void)\n"
139                                                      "{\n"
140                                                      "   v_coords = a_coords;\n"
141                                                      "   gl_Position = a_position;\n"
142                                                      "}\n";
143     const std::string defaultFragSrc = versionDecl + "\n"
144                                                      "in mediump vec4 v_color;\n"
145                                                      "layout(location = 0) out mediump vec4 o_color;\n\n"
146                                                      "void main (void)\n"
147                                                      "{\n"
148                                                      "   o_color = v_color;\n"
149                                                      "}\n";
150 
151     // Fill in specialization parameters.
152     std::map<std::string, std::string> spParams;
153     if (isVertexCase)
154     {
155         spParams["HEADER"]     = versionDecl + "\n"
156                                                "in highp vec4 a_position;\n"
157                                                "in highp vec4 a_coords;\n"
158                                                "out mediump vec4 v_color;";
159         spParams["COORDS"]     = "a_coords";
160         spParams["DST"]        = "v_color";
161         spParams["ASSIGN_POS"] = "gl_Position = a_position;";
162     }
163     else
164     {
165         spParams["HEADER"]     = versionDecl + "\n"
166                                                "in mediump vec4 v_coords;\n"
167                                                "layout(location = 0) out mediump vec4 o_color;";
168         spParams["COORDS"]     = "v_coords";
169         spParams["DST"]        = "o_color";
170         spParams["ASSIGN_POS"] = "";
171     }
172 
173     if (isVertexCase)
174         return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
175                                     StringTemplate(shaderSrc.str()).specialize(spParams).c_str(),
176                                     defaultFragSrc.c_str());
177     else
178         return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
179                                     defaultVertSrc.c_str(),
180                                     StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
181 }
182 
183 class LocalStructTests : public TestCaseGroup
184 {
185 public:
LocalStructTests(Context & context,glu::GLSLVersion glslVersion)186     LocalStructTests(Context &context, glu::GLSLVersion glslVersion)
187         : TestCaseGroup(context, "local", "Local structs")
188         , m_glslVersion(glslVersion)
189     {
190     }
191 
~LocalStructTests(void)192     ~LocalStructTests(void)
193     {
194     }
195 
196     virtual void init(void);
197 
198 private:
199     glu::GLSLVersion m_glslVersion;
200 };
201 
init(void)202 void LocalStructTests::init(void)
203 {
204 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY)                                  \
205     do                                                                                                    \
206     {                                                                                                     \
207         struct Eval_##NAME                                                                                \
208         {                                                                                                 \
209             static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY                                         \
210         };                                                                                                \
211         addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, false,    \
212                                   &Eval_##NAME::eval, DE_NULL, SHADER_SRC));                              \
213         addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, false, \
214                                   &Eval_##NAME::eval, DE_NULL, SHADER_SRC));                              \
215     } while (false)
216 
217     LOCAL_STRUCT_CASE(basic, "Basic struct usage",
218                       LineStream() << "${HEADER}"
219                                    << "uniform int ui_one;"
220                                    << ""
221                                    << "struct S {"
222                                    << "    mediump float   a;"
223                                    << "    mediump vec3    b;"
224                                    << "    int             c;"
225                                    << "};"
226                                    << ""
227                                    << "void main (void)"
228                                    << "{"
229                                    << "    S s = S(${COORDS}.x, vec3(0.0), ui_one);"
230                                    << "    s.b = ${COORDS}.yzw;"
231                                    << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
232                                    << "    ${ASSIGN_POS}"
233                                    << "}",
234                       { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
235 
236     LOCAL_STRUCT_CASE(nested, "Nested struct",
237                       LineStream() << "${HEADER}"
238                                    << "uniform int ui_zero;"
239                                    << "uniform int ui_one;"
240                                    << ""
241                                    << "struct T {"
242                                    << "    int             a;"
243                                    << "    mediump vec2    b;"
244                                    << "};"
245                                    << "struct S {"
246                                    << "    mediump float   a;"
247                                    << "    T               b;"
248                                    << "    int             c;"
249                                    << "};"
250                                    << ""
251                                    << "void main (void)"
252                                    << "{"
253                                    << "    S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
254                                    << "    s.b = T(ui_zero, ${COORDS}.yz);"
255                                    << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
256                                    << "    ${ASSIGN_POS}"
257                                    << "}",
258                       { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
259 
260     LOCAL_STRUCT_CASE(array_member, "Struct with array member",
261                       LineStream() << "${HEADER}"
262                                    << "uniform int ui_one;"
263                                    << ""
264                                    << "struct S {"
265                                    << "    mediump float   a;"
266                                    << "    mediump float   b[3];"
267                                    << "    int             c;"
268                                    << "};"
269                                    << ""
270                                    << "void main (void)"
271                                    << "{"
272                                    << "    S s;"
273                                    << "    s.a = ${COORDS}.w;"
274                                    << "    s.c = ui_one;"
275                                    << "    s.b[0] = ${COORDS}.z;"
276                                    << "    s.b[1] = ${COORDS}.y;"
277                                    << "    s.b[2] = ${COORDS}.x;"
278                                    << "    ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
279                                    << "    ${ASSIGN_POS}"
280                                    << "}",
281                       { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
282 
283     LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing",
284                       LineStream() << "${HEADER}"
285                                    << "uniform int ui_zero;"
286                                    << "uniform int ui_one;"
287                                    << "uniform int ui_two;"
288                                    << ""
289                                    << "struct S {"
290                                    << "    mediump float   a;"
291                                    << "    mediump float   b[3];"
292                                    << "    int             c;"
293                                    << "};"
294                                    << ""
295                                    << "void main (void)"
296                                    << "{"
297                                    << "    S s;"
298                                    << "    s.a = ${COORDS}.w;"
299                                    << "    s.c = ui_one;"
300                                    << "    s.b[0] = ${COORDS}.z;"
301                                    << "    s.b[1] = ${COORDS}.y;"
302                                    << "    s.b[2] = ${COORDS}.x;"
303                                    << "    ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
304                                    << "    ${ASSIGN_POS}"
305                                    << "}",
306                       { c.color.xyz() = c.coords.swizzle(1, 2, 0); });
307 
308     LOCAL_STRUCT_CASE(struct_array, "Struct array",
309                       LineStream() << "${HEADER}"
310                                    << "uniform int ui_zero;"
311                                    << "uniform int ui_one;"
312                                    << "uniform int ui_two;"
313                                    << ""
314                                    << "struct S {"
315                                    << "    mediump float   a;"
316                                    << "    mediump int     b;"
317                                    << "};"
318                                    << ""
319                                    << "void main (void)"
320                                    << "{"
321                                    << "    S s[3];"
322                                    << "    s[0] = S(${COORDS}.x, ui_zero);"
323                                    << "    s[1].a = ${COORDS}.y;"
324                                    << "    s[1].b = ui_one;"
325                                    << "    s[2] = S(${COORDS}.z, ui_two);"
326                                    << "    ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
327                                    << "    ${ASSIGN_POS}"
328                                    << "}",
329                       { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
330 
331     LOCAL_STRUCT_CASE(
332         struct_array_dynamic_index, "Struct array with dynamic indexing",
333         LineStream()
334             << "${HEADER}"
335             << "uniform int ui_zero;"
336             << "uniform int ui_one;"
337             << "uniform int ui_two;"
338             << ""
339             << "struct S {"
340             << "    mediump float   a;"
341             << "    mediump int     b;"
342             << "};"
343             << ""
344             << "void main (void)"
345             << "{"
346             << "    S s[3];"
347             << "    s[0] = S(${COORDS}.x, ui_zero);"
348             << "    s[1].a = ${COORDS}.y;"
349             << "    s[1].b = ui_one;"
350             << "    s[2] = S(${COORDS}.z, ui_two);"
351             << "    ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);"
352             << "    ${ASSIGN_POS}"
353             << "}",
354         { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
355 
356     LOCAL_STRUCT_CASE(
357         nested_struct_array, "Nested struct array",
358         LineStream() << "${HEADER}"
359                      << "uniform int ui_zero;"
360                      << "uniform int ui_one;"
361                      << "uniform int ui_two;"
362                      << "uniform mediump float uf_two;"
363                      << "uniform mediump float uf_three;"
364                      << "uniform mediump float uf_four;"
365                      << "uniform mediump float uf_half;"
366                      << "uniform mediump float uf_third;"
367                      << "uniform mediump float uf_fourth;"
368                      << ""
369                      << "struct T {"
370                      << "    mediump float   a;"
371                      << "    mediump vec2    b[2];"
372                      << "};"
373                      << "struct S {"
374                      << "    mediump float   a;"
375                      << "    T               b[3];"
376                      << "    int             c;"
377                      << "};"
378                      << ""
379                      << "void main (void)"
380                      << "{"
381                      << "    S s[2];"
382                      << ""
383                      << "    // S[0]"
384                      << "    s[0].a         = ${COORDS}.x;"
385                      << "    s[0].b[0].a    = uf_half;"
386                      << "    s[0].b[0].b[0] = ${COORDS}.xy;"
387                      << "    s[0].b[0].b[1] = ${COORDS}.zw;"
388                      << "    s[0].b[1].a    = uf_third;"
389                      << "    s[0].b[1].b[0] = ${COORDS}.zw;"
390                      << "    s[0].b[1].b[1] = ${COORDS}.xy;"
391                      << "    s[0].b[2].a    = uf_fourth;"
392                      << "    s[0].b[2].b[0] = ${COORDS}.xz;"
393                      << "    s[0].b[2].b[1] = ${COORDS}.yw;"
394                      << "    s[0].c         = ui_zero;"
395                      << ""
396                      << "    // S[1]"
397                      << "    s[1].a         = ${COORDS}.w;"
398                      << "    s[1].b[0].a    = uf_two;"
399                      << "    s[1].b[0].b[0] = ${COORDS}.xx;"
400                      << "    s[1].b[0].b[1] = ${COORDS}.yy;"
401                      << "    s[1].b[1].a    = uf_three;"
402                      << "    s[1].b[1].b[0] = ${COORDS}.zz;"
403                      << "    s[1].b[1].b[1] = ${COORDS}.ww;"
404                      << "    s[1].b[2].a    = uf_four;"
405                      << "    s[1].b[2].b[0] = ${COORDS}.yx;"
406                      << "    s[1].b[2].b[1] = ${COORDS}.wz;"
407                      << "    s[1].c         = ui_one;"
408                      << ""
409                      << "    mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5"
410                      << "    mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
411                      << "    mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w "
412                         "+ w) * 0.333"
413                      << "    mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
414                      << "    ${DST} = vec4(r, g, b, a);"
415                      << "    ${ASSIGN_POS}"
416                      << "}",
417         { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
418 
419     LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing",
420                       LineStream() << "${HEADER}"
421                                    << "uniform int ui_zero;"
422                                    << "uniform int ui_one;"
423                                    << "uniform int ui_two;"
424                                    << "uniform mediump float uf_two;"
425                                    << "uniform mediump float uf_three;"
426                                    << "uniform mediump float uf_four;"
427                                    << "uniform mediump float uf_half;"
428                                    << "uniform mediump float uf_third;"
429                                    << "uniform mediump float uf_fourth;"
430                                    << ""
431                                    << "struct T {"
432                                    << "    mediump float   a;"
433                                    << "    mediump vec2    b[2];"
434                                    << "};"
435                                    << "struct S {"
436                                    << "    mediump float   a;"
437                                    << "    T               b[3];"
438                                    << "    int             c;"
439                                    << "};"
440                                    << ""
441                                    << "void main (void)"
442                                    << "{"
443                                    << "    S s[2];"
444                                    << ""
445                                    << "    // S[0]"
446                                    << "    s[0].a         = ${COORDS}.x;"
447                                    << "    s[0].b[0].a    = uf_half;"
448                                    << "    s[0].b[0].b[0] = ${COORDS}.xy;"
449                                    << "    s[0].b[0].b[1] = ${COORDS}.zw;"
450                                    << "    s[0].b[1].a    = uf_third;"
451                                    << "    s[0].b[1].b[0] = ${COORDS}.zw;"
452                                    << "    s[0].b[1].b[1] = ${COORDS}.xy;"
453                                    << "    s[0].b[2].a    = uf_fourth;"
454                                    << "    s[0].b[2].b[0] = ${COORDS}.xz;"
455                                    << "    s[0].b[2].b[1] = ${COORDS}.yw;"
456                                    << "    s[0].c         = ui_zero;"
457                                    << ""
458                                    << "    // S[1]"
459                                    << "    s[1].a         = ${COORDS}.w;"
460                                    << "    s[1].b[0].a    = uf_two;"
461                                    << "    s[1].b[0].b[0] = ${COORDS}.xx;"
462                                    << "    s[1].b[0].b[1] = ${COORDS}.yy;"
463                                    << "    s[1].b[1].a    = uf_three;"
464                                    << "    s[1].b[1].b[0] = ${COORDS}.zz;"
465                                    << "    s[1].b[1].b[1] = ${COORDS}.ww;"
466                                    << "    s[1].b[2].a    = uf_four;"
467                                    << "    s[1].b[2].b[0] = ${COORDS}.yx;"
468                                    << "    s[1].b[2].b[1] = ${COORDS}.wz;"
469                                    << "    s[1].c         = ui_one;"
470                                    << ""
471                                    << "    mediump float r = (s[0].b[ui_one].b[ui_one-1].x + "
472                                       "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5"
473                                    << "    mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * "
474                                       "s[ui_one].b[2].a; // x * 0.25 * 4"
475                                    << "    mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + "
476                                       "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + "
477                                       "w + w) * 0.333"
478                                    << "    mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - "
479                                       "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
480                                    << "    ${DST} = vec4(r, g, b, a);"
481                                    << "    ${ASSIGN_POS}"
482                                    << "}",
483                       { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
484 
485     LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter",
486                       LineStream() << "${HEADER}"
487                                    << "uniform int ui_one;"
488                                    << ""
489                                    << "struct S {"
490                                    << "    mediump float   a;"
491                                    << "    mediump vec3    b;"
492                                    << "    int             c;"
493                                    << "};"
494                                    << ""
495                                    << "mediump vec4 myFunc (S s)"
496                                    << "{"
497                                    << "    return vec4(s.a, s.b.x, s.b.y, s.c);"
498                                    << "}"
499                                    << ""
500                                    << "void main (void)"
501                                    << "{"
502                                    << "    S s = S(${COORDS}.x, vec3(0.0), ui_one);"
503                                    << "    s.b = ${COORDS}.yzw;"
504                                    << "    ${DST} = myFunc(s);"
505                                    << "    ${ASSIGN_POS}"
506                                    << "}",
507                       { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
508 
509     LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter",
510                       LineStream() << "${HEADER}"
511                                    << "uniform int ui_zero;"
512                                    << "uniform int ui_one;"
513                                    << ""
514                                    << "struct T {"
515                                    << "    int             a;"
516                                    << "    mediump vec2    b;"
517                                    << "};"
518                                    << "struct S {"
519                                    << "    mediump float   a;"
520                                    << "    T               b;"
521                                    << "    int             c;"
522                                    << "};"
523                                    << ""
524                                    << "mediump vec4 myFunc (S s)"
525                                    << "{"
526                                    << "    return vec4(s.a, s.b.b, s.b.a + s.c);"
527                                    << "}"
528                                    << ""
529                                    << "void main (void)"
530                                    << "{"
531                                    << "    S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
532                                    << "    s.b = T(ui_zero, ${COORDS}.yz);"
533                                    << "    ${DST} = myFunc(s);"
534                                    << "    ${ASSIGN_POS}"
535                                    << "}",
536                       { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
537 
538     LOCAL_STRUCT_CASE(return, "Struct as a return value",
539                             LineStream() << "${HEADER}"
540                                          << "uniform int ui_one;"
541                                          << ""
542                                          << "struct S {"
543                                          << "    mediump float   a;"
544                                          << "    mediump vec3    b;"
545                                          << "    int             c;"
546                                          << "};"
547                                          << ""
548                                          << "S myFunc (void)"
549                                          << "{"
550                                          << "    S s = S(${COORDS}.x, vec3(0.0), ui_one);"
551                                          << "    s.b = ${COORDS}.yzw;"
552                                          << "    return s;"
553                                          << "}"
554                                          << ""
555                                          << "void main (void)"
556                                          << "{"
557                                          << "    S s = myFunc();"
558                                          << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
559                                          << "    ${ASSIGN_POS}"
560                                          << "}",
561                             { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
562 
563     LOCAL_STRUCT_CASE(return_nested, "Nested struct",
564                       LineStream() << "${HEADER}"
565                                    << "uniform int ui_zero;"
566                                    << "uniform int ui_one;"
567                                    << ""
568                                    << "struct T {"
569                                    << "    int             a;"
570                                    << "    mediump vec2    b;"
571                                    << "};"
572                                    << "struct S {"
573                                    << "    mediump float   a;"
574                                    << "    T               b;"
575                                    << "    int             c;"
576                                    << "};"
577                                    << ""
578                                    << "S myFunc (void)"
579                                    << "{"
580                                    << "    S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
581                                    << "    s.b = T(ui_zero, ${COORDS}.yz);"
582                                    << "    return s;"
583                                    << "}"
584                                    << ""
585                                    << "void main (void)"
586                                    << "{"
587                                    << "    S s = myFunc();"
588                                    << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
589                                    << "    ${ASSIGN_POS}"
590                                    << "}",
591                       { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
592 
593     LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment",
594                       LineStream() << "${HEADER}"
595                                    << "uniform int ui_zero;"
596                                    << "uniform int ui_one;"
597                                    << "uniform mediump float uf_one;"
598                                    << ""
599                                    << "struct S {"
600                                    << "    mediump float   a;"
601                                    << "    mediump vec3    b;"
602                                    << "    int             c;"
603                                    << "};"
604                                    << ""
605                                    << "void main (void)"
606                                    << "{"
607                                    << "    S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
608                                    << "    if (uf_one > 0.0)"
609                                    << "        s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
610                                    << "    ${DST} = vec4(s.a, s.b.xy, s.c);"
611                                    << "    ${ASSIGN_POS}"
612                                    << "}",
613                       { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
614 
615     LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop",
616                       LineStream() << "${HEADER}"
617                                    << "uniform int ui_zero;"
618                                    << "uniform int ui_one;"
619                                    << ""
620                                    << "struct S {"
621                                    << "    mediump float   a;"
622                                    << "    mediump vec3    b;"
623                                    << "    int             c;"
624                                    << "};"
625                                    << ""
626                                    << "void main (void)"
627                                    << "{"
628                                    << "    S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
629                                    << "    for (int i = 0; i < 3; i++)"
630                                    << "    {"
631                                    << "        if (i == 1)"
632                                    << "            s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
633                                    << "    }"
634                                    << "    ${DST} = vec4(s.a, s.b.xy, s.c);"
635                                    << "    ${ASSIGN_POS}"
636                                    << "}",
637                       { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
638 
639     LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop",
640                       LineStream() << "${HEADER}"
641                                    << "uniform int ui_zero;"
642                                    << "uniform int ui_one;"
643                                    << "uniform int ui_three;"
644                                    << ""
645                                    << "struct S {"
646                                    << "    mediump float   a;"
647                                    << "    mediump vec3    b;"
648                                    << "    int             c;"
649                                    << "};"
650                                    << ""
651                                    << "void main (void)"
652                                    << "{"
653                                    << "    S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
654                                    << "    for (int i = 0; i < ui_three; i++)"
655                                    << "    {"
656                                    << "        if (i == ui_one)"
657                                    << "            s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
658                                    << "    }"
659                                    << "    ${DST} = vec4(s.a, s.b.xy, s.c);"
660                                    << "    ${ASSIGN_POS}"
661                                    << "}",
662                       { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
663 
664     LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct",
665                       LineStream() << "${HEADER}"
666                                    << "uniform int ui_zero;"
667                                    << "uniform int ui_one;"
668                                    << "uniform mediump float uf_one;"
669                                    << ""
670                                    << "struct T {"
671                                    << "    int             a;"
672                                    << "    mediump vec2    b;"
673                                    << "};"
674                                    << "struct S {"
675                                    << "    mediump float   a;"
676                                    << "    T               b;"
677                                    << "    int             c;"
678                                    << "};"
679                                    << ""
680                                    << "void main (void)"
681                                    << "{"
682                                    << "    S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
683                                    << "    if (uf_one > 0.0)"
684                                    << "        s.b = T(ui_zero, ${COORDS}.zw);"
685                                    << "    ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
686                                    << "    ${ASSIGN_POS}"
687                                    << "}",
688                       { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
689 
690     LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop",
691                       LineStream() << "${HEADER}"
692                                    << "uniform int ui_zero;"
693                                    << "uniform int ui_one;"
694                                    << "uniform mediump float uf_one;"
695                                    << ""
696                                    << "struct T {"
697                                    << "    int             a;"
698                                    << "    mediump vec2    b;"
699                                    << "};"
700                                    << "struct S {"
701                                    << "    mediump float   a;"
702                                    << "    T               b;"
703                                    << "    int             c;"
704                                    << "};"
705                                    << ""
706                                    << "void main (void)"
707                                    << "{"
708                                    << "    S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
709                                    << "    for (int i = 0; i < 3; i++)"
710                                    << "    {"
711                                    << "        if (i == 1)"
712                                    << "            s.b = T(ui_zero, ${COORDS}.zw);"
713                                    << "    }"
714                                    << "    ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
715                                    << "    ${ASSIGN_POS}"
716                                    << "}",
717                       { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
718 
719     LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop",
720                       LineStream() << "${HEADER}"
721                                    << "uniform int ui_zero;"
722                                    << "uniform int ui_one;"
723                                    << "uniform int ui_three;"
724                                    << "uniform mediump float uf_one;"
725                                    << ""
726                                    << "struct T {"
727                                    << "    int             a;"
728                                    << "    mediump vec2    b;"
729                                    << "};"
730                                    << "struct S {"
731                                    << "    mediump float   a;"
732                                    << "    T               b;"
733                                    << "    int             c;"
734                                    << "};"
735                                    << ""
736                                    << "void main (void)"
737                                    << "{"
738                                    << "    S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
739                                    << "    for (int i = 0; i < ui_three; i++)"
740                                    << "    {"
741                                    << "        if (i == ui_one)"
742                                    << "            s.b = T(ui_zero, ${COORDS}.zw);"
743                                    << "    }"
744                                    << "    ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
745                                    << "    ${ASSIGN_POS}"
746                                    << "}",
747                       { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
748 
749     LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop",
750                       LineStream() << "${HEADER}"
751                                    << "uniform int ui_zero;"
752                                    << "uniform int ui_one;"
753                                    << "uniform int ui_two;"
754                                    << ""
755                                    << "struct S {"
756                                    << "    mediump float   a;"
757                                    << "    mediump int     b;"
758                                    << "};"
759                                    << ""
760                                    << "void main (void)"
761                                    << "{"
762                                    << "    S s[3];"
763                                    << "    s[0] = S(${COORDS}.x, ui_zero);"
764                                    << "    s[1].a = ${COORDS}.y;"
765                                    << "    s[1].b = -ui_one;"
766                                    << "    s[2] = S(${COORDS}.z, ui_two);"
767                                    << ""
768                                    << "    mediump float rgb[3];"
769                                    << "    int alpha = 0;"
770                                    << "    for (int i = 0; i < 3; i++)"
771                                    << "    {"
772                                    << "        rgb[i] = s[2-i].a;"
773                                    << "        alpha += s[i].b;"
774                                    << "    }"
775                                    << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
776                                    << "    ${ASSIGN_POS}"
777                                    << "}",
778                       { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
779 
780     LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop",
781                       LineStream() << "${HEADER}"
782                                    << "uniform int ui_zero;"
783                                    << "uniform int ui_one;"
784                                    << "uniform int ui_two;"
785                                    << "uniform mediump float uf_two;"
786                                    << "uniform mediump float uf_three;"
787                                    << "uniform mediump float uf_four;"
788                                    << "uniform mediump float uf_half;"
789                                    << "uniform mediump float uf_third;"
790                                    << "uniform mediump float uf_fourth;"
791                                    << "uniform mediump float uf_sixth;"
792                                    << ""
793                                    << "struct T {"
794                                    << "    mediump float   a;"
795                                    << "    mediump vec2    b[2];"
796                                    << "};"
797                                    << "struct S {"
798                                    << "    mediump float   a;"
799                                    << "    T               b[3];"
800                                    << "    int             c;"
801                                    << "};"
802                                    << ""
803                                    << "void main (void)"
804                                    << "{"
805                                    << "    S s[2];"
806                                    << ""
807                                    << "    // S[0]"
808                                    << "    s[0].a         = ${COORDS}.x;"
809                                    << "    s[0].b[0].a    = uf_half;"
810                                    << "    s[0].b[0].b[0] = ${COORDS}.yx;"
811                                    << "    s[0].b[0].b[1] = ${COORDS}.zx;"
812                                    << "    s[0].b[1].a    = uf_third;"
813                                    << "    s[0].b[1].b[0] = ${COORDS}.yy;"
814                                    << "    s[0].b[1].b[1] = ${COORDS}.wy;"
815                                    << "    s[0].b[2].a    = uf_fourth;"
816                                    << "    s[0].b[2].b[0] = ${COORDS}.zx;"
817                                    << "    s[0].b[2].b[1] = ${COORDS}.zy;"
818                                    << "    s[0].c         = ui_zero;"
819                                    << ""
820                                    << "    // S[1]"
821                                    << "    s[1].a         = ${COORDS}.w;"
822                                    << "    s[1].b[0].a    = uf_two;"
823                                    << "    s[1].b[0].b[0] = ${COORDS}.zx;"
824                                    << "    s[1].b[0].b[1] = ${COORDS}.zy;"
825                                    << "    s[1].b[1].a    = uf_three;"
826                                    << "    s[1].b[1].b[0] = ${COORDS}.zz;"
827                                    << "    s[1].b[1].b[1] = ${COORDS}.ww;"
828                                    << "    s[1].b[2].a    = uf_four;"
829                                    << "    s[1].b[2].b[0] = ${COORDS}.yx;"
830                                    << "    s[1].b[2].b[1] = ${COORDS}.wz;"
831                                    << "    s[1].c         = ui_one;"
832                                    << ""
833                                    << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
834                                    << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
835                                    << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
836                                    << "    mediump float a = 1.0;"
837                                    << "    for (int i = 0; i < 2; i++)"
838                                    << "    {"
839                                    << "        for (int j = 0; j < 3; j++)"
840                                    << "        {"
841                                    << "            r += s[0].b[j].b[i].y;"
842                                    << "            g += s[i].b[j].b[0].x;"
843                                    << "            b += s[i].b[j].b[1].x;"
844                                    << "            a *= s[i].b[j].a;"
845                                    << "        }"
846                                    << "    }"
847                                    << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
848                                    << "    ${ASSIGN_POS}"
849                                    << "}",
850                       { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
851 
852     LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop",
853                       LineStream() << "${HEADER}"
854                                    << "uniform int ui_zero;"
855                                    << "uniform int ui_one;"
856                                    << "uniform int ui_two;"
857                                    << "uniform int ui_three;"
858                                    << ""
859                                    << "struct S {"
860                                    << "    mediump float   a;"
861                                    << "    mediump int     b;"
862                                    << "};"
863                                    << ""
864                                    << "void main (void)"
865                                    << "{"
866                                    << "    S s[3];"
867                                    << "    s[0] = S(${COORDS}.x, ui_zero);"
868                                    << "    s[1].a = ${COORDS}.y;"
869                                    << "    s[1].b = -ui_one;"
870                                    << "    s[2] = S(${COORDS}.z, ui_two);"
871                                    << ""
872                                    << "    mediump float rgb[3];"
873                                    << "    int alpha = 0;"
874                                    << "    for (int i = 0; i < ui_three; i++)"
875                                    << "    {"
876                                    << "        rgb[i] = s[2-i].a;"
877                                    << "        alpha += s[i].b;"
878                                    << "    }"
879                                    << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
880                                    << "    ${ASSIGN_POS}"
881                                    << "}",
882                       { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
883 
884     LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop",
885                       LineStream() << "${HEADER}"
886                                    << "uniform int ui_zero;"
887                                    << "uniform int ui_one;"
888                                    << "uniform int ui_two;"
889                                    << "uniform int ui_three;"
890                                    << "uniform mediump float uf_two;"
891                                    << "uniform mediump float uf_three;"
892                                    << "uniform mediump float uf_four;"
893                                    << "uniform mediump float uf_half;"
894                                    << "uniform mediump float uf_third;"
895                                    << "uniform mediump float uf_fourth;"
896                                    << "uniform mediump float uf_sixth;"
897                                    << ""
898                                    << "struct T {"
899                                    << "    mediump float   a;"
900                                    << "    mediump vec2    b[2];"
901                                    << "};"
902                                    << "struct S {"
903                                    << "    mediump float   a;"
904                                    << "    T               b[3];"
905                                    << "    int             c;"
906                                    << "};"
907                                    << ""
908                                    << "void main (void)"
909                                    << "{"
910                                    << "    S s[2];"
911                                    << ""
912                                    << "    // S[0]"
913                                    << "    s[0].a         = ${COORDS}.x;"
914                                    << "    s[0].b[0].a    = uf_half;"
915                                    << "    s[0].b[0].b[0] = ${COORDS}.yx;"
916                                    << "    s[0].b[0].b[1] = ${COORDS}.zx;"
917                                    << "    s[0].b[1].a    = uf_third;"
918                                    << "    s[0].b[1].b[0] = ${COORDS}.yy;"
919                                    << "    s[0].b[1].b[1] = ${COORDS}.wy;"
920                                    << "    s[0].b[2].a    = uf_fourth;"
921                                    << "    s[0].b[2].b[0] = ${COORDS}.zx;"
922                                    << "    s[0].b[2].b[1] = ${COORDS}.zy;"
923                                    << "    s[0].c         = ui_zero;"
924                                    << ""
925                                    << "    // S[1]"
926                                    << "    s[1].a         = ${COORDS}.w;"
927                                    << "    s[1].b[0].a    = uf_two;"
928                                    << "    s[1].b[0].b[0] = ${COORDS}.zx;"
929                                    << "    s[1].b[0].b[1] = ${COORDS}.zy;"
930                                    << "    s[1].b[1].a    = uf_three;"
931                                    << "    s[1].b[1].b[0] = ${COORDS}.zz;"
932                                    << "    s[1].b[1].b[1] = ${COORDS}.ww;"
933                                    << "    s[1].b[2].a    = uf_four;"
934                                    << "    s[1].b[2].b[0] = ${COORDS}.yx;"
935                                    << "    s[1].b[2].b[1] = ${COORDS}.wz;"
936                                    << "    s[1].c         = ui_one;"
937                                    << ""
938                                    << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
939                                    << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
940                                    << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
941                                    << "    mediump float a = 1.0;"
942                                    << "    for (int i = 0; i < ui_two; i++)"
943                                    << "    {"
944                                    << "        for (int j = 0; j < ui_three; j++)"
945                                    << "        {"
946                                    << "            r += s[0].b[j].b[i].y;"
947                                    << "            g += s[i].b[j].b[0].x;"
948                                    << "            b += s[i].b[j].b[1].x;"
949                                    << "            a *= s[i].b[j].a;"
950                                    << "        }"
951                                    << "    }"
952                                    << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
953                                    << "    ${ASSIGN_POS}"
954                                    << "}",
955                       { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
956 
957     LOCAL_STRUCT_CASE(basic_equal, "Basic struct equality",
958                       LineStream() << "${HEADER}"
959                                    << "uniform int ui_one;"
960                                    << "uniform int ui_two;"
961                                    << ""
962                                    << "struct S {"
963                                    << "    mediump float    a;"
964                                    << "    mediump vec3    b;"
965                                    << "    int                c;"
966                                    << "};"
967                                    << ""
968                                    << "void main (void)"
969                                    << "{"
970                                    << "    S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
971                                    << "    S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
972                                    << "    S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
973                                    << "    S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
974                                    << "    ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
975                                    << "    if (a == b) ${DST}.x = 1.0;"
976                                    << "    if (a == c) ${DST}.y = 1.0;"
977                                    << "    if (a == d) ${DST}.z = 1.0;"
978                                    << "    ${ASSIGN_POS}"
979                                    << "}",
980                       {
981                           if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f))
982                               c.color.x() = 1.0f;
983                           if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f))
984                               c.color.y() = 1.0f;
985                       });
986 
987     LOCAL_STRUCT_CASE(basic_not_equal, "Basic struct equality",
988                       LineStream() << "${HEADER}"
989                                    << "uniform int ui_one;"
990                                    << "uniform int ui_two;"
991                                    << ""
992                                    << "struct S {"
993                                    << "    mediump float    a;"
994                                    << "    mediump vec3    b;"
995                                    << "    int                c;"
996                                    << "};"
997                                    << ""
998                                    << "void main (void)"
999                                    << "{"
1000                                    << "    S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1001                                    << "    S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);"
1002                                    << "    S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);"
1003                                    << "    S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);"
1004                                    << "    ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1005                                    << "    if (a != b) ${DST}.x = 1.0;"
1006                                    << "    if (a != c) ${DST}.y = 1.0;"
1007                                    << "    if (a != d) ${DST}.z = 1.0;"
1008                                    << "    ${ASSIGN_POS}"
1009                                    << "}",
1010                       {
1011                           if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f))
1012                               c.color.x() = 1.0f;
1013                           if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f))
1014                               c.color.y() = 1.0f;
1015                           c.color.z() = 1.0f;
1016                       });
1017 
1018     LOCAL_STRUCT_CASE(
1019         nested_equal, "Nested struct struct equality",
1020         LineStream() << "${HEADER}"
1021                      << "uniform int ui_one;"
1022                      << "uniform int ui_two;"
1023                      << ""
1024                      << "struct T {"
1025                      << "    mediump vec3    a;"
1026                      << "    int                b;"
1027                      << "};"
1028                      << "struct S {"
1029                      << "    mediump float    a;"
1030                      << "    T                b;"
1031                      << "    int                c;"
1032                      << "};"
1033                      << ""
1034                      << "void main (void)"
1035                      << "{"
1036                      << "    S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1037                      << "    S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1038                      << "    S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1039                      << "    S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1040                      << "    ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1041                      << "    if (a == b) ${DST}.x = 1.0;"
1042                      << "    if (a == c) ${DST}.y = 1.0;"
1043                      << "    if (a == d) ${DST}.z = 1.0;"
1044                      << "    ${ASSIGN_POS}"
1045                      << "}",
1046         {
1047             if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f))
1048                 c.color.x() = 1.0f;
1049             if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f))
1050                 c.color.y() = 1.0f;
1051         });
1052 
1053     LOCAL_STRUCT_CASE(
1054         nested_not_equal, "Nested struct struct equality",
1055         LineStream() << "${HEADER}"
1056                      << "uniform int ui_one;"
1057                      << "uniform int ui_two;"
1058                      << ""
1059                      << "struct T {"
1060                      << "    mediump vec3    a;"
1061                      << "    int                b;"
1062                      << "};"
1063                      << "struct S {"
1064                      << "    mediump float    a;"
1065                      << "    T                b;"
1066                      << "    int                c;"
1067                      << "};"
1068                      << ""
1069                      << "void main (void)"
1070                      << "{"
1071                      << "    S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1072                      << "    S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);"
1073                      << "    S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);"
1074                      << "    S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);"
1075                      << "    ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1076                      << "    if (a != b) ${DST}.x = 1.0;"
1077                      << "    if (a != c) ${DST}.y = 1.0;"
1078                      << "    if (a != d) ${DST}.z = 1.0;"
1079                      << "    ${ASSIGN_POS}"
1080                      << "}",
1081         {
1082             if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f))
1083                 c.color.x() = 1.0f;
1084             if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f))
1085                 c.color.y() = 1.0f;
1086             c.color.z() = 1.0f;
1087         });
1088 
1089     LOCAL_STRUCT_CASE(array_member_equality, "Struct with array members equality",
1090                       LineStream() << "${HEADER}"
1091                                    << ""
1092                                    << "struct S {"
1093                                    << "    bool    m[2];"
1094                                    << "};"
1095                                    << ""
1096                                    << "void main (void)"
1097                                    << "{"
1098                                    << "    S a;"
1099                                    << "    a.m[0] = true;"
1100                                    << "    a.m[1] = false;"
1101                                    << ""
1102                                    << "    S b;"
1103                                    << "    b.m[0] = true;"
1104                                    << "    b.m[1] = false;"
1105                                    << ""
1106                                    << "    S c;"
1107                                    << "    c.m[0] = true;"
1108                                    << "    c.m[1] = true;"
1109                                    << ""
1110                                    << "    ${DST} = vec4(0.0, 0.0, 1.0, 1.0);"
1111                                    << "    if (a == b) ${DST}.x = 1.0;"
1112                                    << "    if (a != c) ${DST}.y = 1.0;"
1113                                    << "    ${ASSIGN_POS}"
1114                                    << "}",
1115                       {
1116                           c.color.x() = 1.0f;
1117                           c.color.y() = 1.0f;
1118                           c.color.z() = 1.0f;
1119                       });
1120 }
1121 
1122 class UniformStructTests : public TestCaseGroup
1123 {
1124 public:
UniformStructTests(Context & context,glu::GLSLVersion glslVersion)1125     UniformStructTests(Context &context, glu::GLSLVersion glslVersion)
1126         : TestCaseGroup(context, "uniform", "Uniform structs")
1127         , m_glslVersion(glslVersion)
1128     {
1129     }
1130 
~UniformStructTests(void)1131     ~UniformStructTests(void)
1132     {
1133     }
1134 
1135     virtual void init(void);
1136 
1137 private:
1138     glu::GLSLVersion m_glslVersion;
1139 };
1140 
1141 namespace
1142 {
1143 
1144 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + NAME).c_str())
1145 
1146 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM)                                                            \
1147     void setUniform(const glw::Functions &gl, uint32_t programID, const char *name, const tcu::VECTYPE &vec) \
1148     {                                                                                                        \
1149         int loc = gl.getUniformLocation(programID, name);                                                    \
1150         SETUNIFORM(loc, 1, vec.getPtr());                                                                    \
1151         CHECK_SET_UNIFORM(name);                                                                             \
1152     }                                                                                                        \
1153     struct SetUniform##VECTYPE##Unused_s                                                                     \
1154     {                                                                                                        \
1155         int unused;                                                                                          \
1156     }
1157 
1158 #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM)                                                        \
1159     void setUniform(const glw::Functions &gl, uint32_t programID, const char *name, const tcu::VECTYPE *vec, \
1160                     int arraySize)                                                                           \
1161     {                                                                                                        \
1162         int loc = gl.getUniformLocation(programID, name);                                                    \
1163         SETUNIFORM(loc, arraySize, vec->getPtr());                                                           \
1164         CHECK_SET_UNIFORM(name);                                                                             \
1165     }                                                                                                        \
1166     struct SetUniformPtr##VECTYPE##Unused_s                                                                  \
1167     {                                                                                                        \
1168         int unused;                                                                                          \
1169     }
1170 
1171 MAKE_SET_VEC_UNIFORM(Vec2, gl.uniform2fv);
1172 MAKE_SET_VEC_UNIFORM(Vec3, gl.uniform3fv);
1173 MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv);
1174 
setUniform(const glw::Functions & gl,uint32_t programID,const char * name,float value)1175 void setUniform(const glw::Functions &gl, uint32_t programID, const char *name, float value)
1176 {
1177     int loc = gl.getUniformLocation(programID, name);
1178     gl.uniform1f(loc, value);
1179     CHECK_SET_UNIFORM(name);
1180 }
1181 
setUniform(const glw::Functions & gl,uint32_t programID,const char * name,int value)1182 void setUniform(const glw::Functions &gl, uint32_t programID, const char *name, int value)
1183 {
1184     int loc = gl.getUniformLocation(programID, name);
1185     gl.uniform1i(loc, value);
1186     CHECK_SET_UNIFORM(name);
1187 }
1188 
setUniform(const glw::Functions & gl,uint32_t programID,const char * name,const float * value,int arraySize)1189 void setUniform(const glw::Functions &gl, uint32_t programID, const char *name, const float *value, int arraySize)
1190 {
1191     int loc = gl.getUniformLocation(programID, name);
1192     gl.uniform1fv(loc, arraySize, value);
1193     CHECK_SET_UNIFORM(name);
1194 }
1195 
1196 } // namespace
1197 
init(void)1198 void UniformStructTests::init(void)
1199 {
1200 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY)      \
1201     do                                                                                                       \
1202     {                                                                                                        \
1203         struct SetUniforms_##NAME                                                                            \
1204         {                                                                                                    \
1205             static void setUniforms(const glw::Functions &gl, uint32_t programID,                            \
1206                                     const tcu::Vec4 &constCoords) SET_UNIFORMS_BODY                          \
1207         };                                                                                                   \
1208         struct Eval_##NAME                                                                                   \
1209         {                                                                                                    \
1210             static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY                                            \
1211         };                                                                                                   \
1212         addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, TEXTURES,    \
1213                                   Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC));          \
1214         addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, TEXTURES, \
1215                                   Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC));          \
1216     } while (false)
1217 
1218     UNIFORM_STRUCT_CASE(
1219         basic, "Basic struct usage", false,
1220         LineStream() << "${HEADER}"
1221                      << "uniform int ui_one;"
1222                      << ""
1223                      << "struct S {"
1224                      << "    mediump float   a;"
1225                      << "    mediump vec3    b;"
1226                      << "    int             c;"
1227                      << "};"
1228                      << "uniform S s;"
1229                      << ""
1230                      << "void main (void)"
1231                      << "{"
1232                      << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1233                      << "    ${ASSIGN_POS}"
1234                      << "}",
1235         {
1236             setUniform(gl, programID, "s.a", constCoords.x());
1237             setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1238             setUniform(gl, programID, "s.c", 1);
1239         },
1240         { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1241 
1242     UNIFORM_STRUCT_CASE(
1243         nested, "Nested struct", false,
1244         LineStream() << "${HEADER}"
1245                      << "uniform int ui_zero;"
1246                      << "uniform int ui_one;"
1247                      << ""
1248                      << "struct T {"
1249                      << "    int             a;"
1250                      << "    mediump vec2    b;"
1251                      << "};"
1252                      << "struct S {"
1253                      << "    mediump float   a;"
1254                      << "    T               b;"
1255                      << "    int             c;"
1256                      << "};"
1257                      << "uniform S s;"
1258                      << ""
1259                      << "void main (void)"
1260                      << "{"
1261                      << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1262                      << "    ${ASSIGN_POS}"
1263                      << "}",
1264         {
1265             setUniform(gl, programID, "s.a", constCoords.x());
1266             setUniform(gl, programID, "s.b.a", 0);
1267             setUniform(gl, programID, "s.b.b", constCoords.swizzle(1, 2));
1268             setUniform(gl, programID, "s.c", 1);
1269         },
1270         { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1271 
1272     UNIFORM_STRUCT_CASE(
1273         array_member, "Struct with array member", false,
1274         LineStream() << "${HEADER}"
1275                      << "uniform int ui_one;"
1276                      << ""
1277                      << "struct S {"
1278                      << "    mediump float   a;"
1279                      << "    mediump float   b[3];"
1280                      << "    int             c;"
1281                      << "};"
1282                      << "uniform S s;"
1283                      << ""
1284                      << "void main (void)"
1285                      << "{"
1286                      << "    ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1287                      << "    ${ASSIGN_POS}"
1288                      << "}",
1289         {
1290             setUniform(gl, programID, "s.a", constCoords.w());
1291             setUniform(gl, programID, "s.c", 1);
1292 
1293             float b[3];
1294             b[0] = constCoords.z();
1295             b[1] = constCoords.y();
1296             b[2] = constCoords.x();
1297             setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1298         },
1299         { c.color.xyz() = c.constCoords.swizzle(3, 2, 1); });
1300 
1301     UNIFORM_STRUCT_CASE(
1302         array_member_dynamic_index, "Struct with array member, dynamic indexing", false,
1303         LineStream() << "${HEADER}"
1304                      << "uniform int ui_zero;"
1305                      << "uniform int ui_one;"
1306                      << "uniform int ui_two;"
1307                      << ""
1308                      << "struct S {"
1309                      << "    mediump float   a;"
1310                      << "    mediump float   b[3];"
1311                      << "    int             c;"
1312                      << "};"
1313                      << "uniform S s;"
1314                      << ""
1315                      << "void main (void)"
1316                      << "{"
1317                      << "    ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1318                      << "    ${ASSIGN_POS}"
1319                      << "}",
1320         {
1321             setUniform(gl, programID, "s.a", constCoords.w());
1322             setUniform(gl, programID, "s.c", 1);
1323 
1324             float b[3];
1325             b[0] = constCoords.z();
1326             b[1] = constCoords.y();
1327             b[2] = constCoords.x();
1328             setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1329         },
1330         { c.color.xyz() = c.constCoords.swizzle(1, 2, 0); });
1331 
1332     UNIFORM_STRUCT_CASE(
1333         struct_array, "Struct array", false,
1334         LineStream() << "${HEADER}"
1335                      << "uniform int ui_zero;"
1336                      << "uniform int ui_one;"
1337                      << "uniform int ui_two;"
1338                      << ""
1339                      << "struct S {"
1340                      << "    mediump float   a;"
1341                      << "    mediump int     b;"
1342                      << "};"
1343                      << "uniform S s[3];"
1344                      << ""
1345                      << "void main (void)"
1346                      << "{"
1347                      << "    ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1348                      << "    ${ASSIGN_POS}"
1349                      << "}",
1350         {
1351             setUniform(gl, programID, "s[0].a", constCoords.x());
1352             setUniform(gl, programID, "s[0].b", 0);
1353             setUniform(gl, programID, "s[1].a", constCoords.y());
1354             setUniform(gl, programID, "s[1].b", 1);
1355             setUniform(gl, programID, "s[2].a", constCoords.z());
1356             setUniform(gl, programID, "s[2].b", 2);
1357         },
1358         { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1359 
1360     UNIFORM_STRUCT_CASE(
1361         struct_array_dynamic_index, "Struct array with dynamic indexing", false,
1362         LineStream()
1363             << "${HEADER}"
1364             << "uniform int ui_zero;"
1365             << "uniform int ui_one;"
1366             << "uniform int ui_two;"
1367             << ""
1368             << "struct S {"
1369             << "    mediump float   a;"
1370             << "    mediump int     b;"
1371             << "};"
1372             << "uniform S s[3];"
1373             << ""
1374             << "void main (void)"
1375             << "{"
1376             << "    ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);"
1377             << "    ${ASSIGN_POS}"
1378             << "}",
1379         {
1380             setUniform(gl, programID, "s[0].a", constCoords.x());
1381             setUniform(gl, programID, "s[0].b", 0);
1382             setUniform(gl, programID, "s[1].a", constCoords.y());
1383             setUniform(gl, programID, "s[1].b", 1);
1384             setUniform(gl, programID, "s[2].a", constCoords.z());
1385             setUniform(gl, programID, "s[2].b", 2);
1386         },
1387         { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1388 
1389     UNIFORM_STRUCT_CASE(
1390         nested_struct_array, "Nested struct array", false,
1391         LineStream() << "${HEADER}"
1392                      << "struct T {"
1393                      << "    mediump float   a;"
1394                      << "    mediump vec2    b[2];"
1395                      << "};"
1396                      << "struct S {"
1397                      << "    mediump float   a;"
1398                      << "    T               b[3];"
1399                      << "    int             c;"
1400                      << "};"
1401                      << "uniform S s[2];"
1402                      << ""
1403                      << "void main (void)"
1404                      << "{"
1405                      << "    mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5"
1406                      << "    mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1407                      << "    mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w "
1408                         "+ w) * 0.333"
1409                      << "    mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1410                      << "    ${DST} = vec4(r, g, b, a);"
1411                      << "    ${ASSIGN_POS}"
1412                      << "}",
1413         {
1414             tcu::Vec2 arr[2];
1415 
1416             setUniform(gl, programID, "s[0].a", constCoords.x());
1417             arr[0] = constCoords.swizzle(0, 1);
1418             arr[1] = constCoords.swizzle(2, 3);
1419             setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1420             setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1421             arr[0] = constCoords.swizzle(2, 3);
1422             arr[1] = constCoords.swizzle(0, 1);
1423             setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1424             setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1425             arr[0] = constCoords.swizzle(0, 2);
1426             arr[1] = constCoords.swizzle(1, 3);
1427             setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1428             setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1429             setUniform(gl, programID, "s[0].c", 0);
1430 
1431             setUniform(gl, programID, "s[1].a", constCoords.w());
1432             arr[0] = constCoords.swizzle(0, 0);
1433             arr[1] = constCoords.swizzle(1, 1);
1434             setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1435             setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1436             arr[0] = constCoords.swizzle(2, 2);
1437             arr[1] = constCoords.swizzle(3, 3);
1438             setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1439             setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1440             arr[0] = constCoords.swizzle(1, 0);
1441             arr[1] = constCoords.swizzle(3, 2);
1442             setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1443             setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1444             setUniform(gl, programID, "s[1].c", 1);
1445         },
1446         { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
1447 
1448     UNIFORM_STRUCT_CASE(
1449         nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false,
1450         LineStream() << "${HEADER}"
1451                      << "uniform int ui_zero;"
1452                      << "uniform int ui_one;"
1453                      << "uniform int ui_two;"
1454                      << ""
1455                      << "struct T {"
1456                      << "    mediump float   a;"
1457                      << "    mediump vec2    b[2];"
1458                      << "};"
1459                      << "struct S {"
1460                      << "    mediump float   a;"
1461                      << "    T               b[3];"
1462                      << "    int             c;"
1463                      << "};"
1464                      << "uniform S s[2];"
1465                      << ""
1466                      << "void main (void)"
1467                      << "{"
1468                      << "    mediump float r = (s[0].b[ui_one].b[ui_one-1].x + "
1469                         "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5"
1470                      << "    mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a "
1471                         "* s[ui_one].b[2].a; // x * 0.25 * 4"
1472                      << "    mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + "
1473                         "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w "
1474                         "+ w + w) * 0.333"
1475                      << "    mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - "
1476                         "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
1477                      << "    ${DST} = vec4(r, g, b, a);"
1478                      << "    ${ASSIGN_POS}"
1479                      << "}",
1480         {
1481             tcu::Vec2 arr[2];
1482 
1483             setUniform(gl, programID, "s[0].a", constCoords.x());
1484             arr[0] = constCoords.swizzle(0, 1);
1485             arr[1] = constCoords.swizzle(2, 3);
1486             setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1487             setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1488             arr[0] = constCoords.swizzle(2, 3);
1489             arr[1] = constCoords.swizzle(0, 1);
1490             setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1491             setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1492             arr[0] = constCoords.swizzle(0, 2);
1493             arr[1] = constCoords.swizzle(1, 3);
1494             setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1495             setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1496             setUniform(gl, programID, "s[0].c", 0);
1497 
1498             setUniform(gl, programID, "s[1].a", constCoords.w());
1499             arr[0] = constCoords.swizzle(0, 0);
1500             arr[1] = constCoords.swizzle(1, 1);
1501             setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1502             setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1503             arr[0] = constCoords.swizzle(2, 2);
1504             arr[1] = constCoords.swizzle(3, 3);
1505             setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1506             setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1507             arr[0] = constCoords.swizzle(1, 0);
1508             arr[1] = constCoords.swizzle(3, 2);
1509             setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1510             setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1511             setUniform(gl, programID, "s[1].c", 1);
1512         },
1513         { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
1514 
1515     UNIFORM_STRUCT_CASE(
1516         loop_struct_array, "Struct array usage in loop", false,
1517         LineStream() << "${HEADER}"
1518                      << "uniform int ui_zero;"
1519                      << "uniform int ui_one;"
1520                      << "uniform int ui_two;"
1521                      << ""
1522                      << "struct S {"
1523                      << "    mediump float   a;"
1524                      << "    mediump int     b;"
1525                      << "};"
1526                      << "uniform S s[3];"
1527                      << ""
1528                      << "void main (void)"
1529                      << "{"
1530                      << "    mediump float rgb[3];"
1531                      << "    int alpha = 0;"
1532                      << "    for (int i = 0; i < 3; i++)"
1533                      << "    {"
1534                      << "        rgb[i] = s[2-i].a;"
1535                      << "        alpha += s[i].b;"
1536                      << "    }"
1537                      << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1538                      << "    ${ASSIGN_POS}"
1539                      << "}",
1540         {
1541             setUniform(gl, programID, "s[0].a", constCoords.x());
1542             setUniform(gl, programID, "s[0].b", 0);
1543             setUniform(gl, programID, "s[1].a", constCoords.y());
1544             setUniform(gl, programID, "s[1].b", -1);
1545             setUniform(gl, programID, "s[2].a", constCoords.z());
1546             setUniform(gl, programID, "s[2].b", 2);
1547         },
1548         { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1549 
1550     UNIFORM_STRUCT_CASE(
1551         loop_nested_struct_array, "Nested struct array usage in loop", false,
1552         LineStream() << "${HEADER}"
1553                      << "uniform int ui_zero;"
1554                      << "uniform int ui_one;"
1555                      << "uniform int ui_two;"
1556                      << "uniform mediump float uf_two;"
1557                      << "uniform mediump float uf_three;"
1558                      << "uniform mediump float uf_four;"
1559                      << "uniform mediump float uf_half;"
1560                      << "uniform mediump float uf_third;"
1561                      << "uniform mediump float uf_fourth;"
1562                      << "uniform mediump float uf_sixth;"
1563                      << ""
1564                      << "struct T {"
1565                      << "    mediump float   a;"
1566                      << "    mediump vec2    b[2];"
1567                      << "};"
1568                      << "struct S {"
1569                      << "    mediump float   a;"
1570                      << "    T               b[3];"
1571                      << "    int             c;"
1572                      << "};"
1573                      << "uniform S s[2];"
1574                      << ""
1575                      << "void main (void)"
1576                      << "{"
1577                      << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1578                      << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1579                      << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1580                      << "    mediump float a = 1.0;"
1581                      << "    for (int i = 0; i < 2; i++)"
1582                      << "    {"
1583                      << "        for (int j = 0; j < 3; j++)"
1584                      << "        {"
1585                      << "            r += s[0].b[j].b[i].y;"
1586                      << "            g += s[i].b[j].b[0].x;"
1587                      << "            b += s[i].b[j].b[1].x;"
1588                      << "            a *= s[i].b[j].a;"
1589                      << "        }"
1590                      << "    }"
1591                      << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1592                      << "    ${ASSIGN_POS}"
1593                      << "}",
1594         {
1595             tcu::Vec2 arr[2];
1596 
1597             setUniform(gl, programID, "s[0].a", constCoords.x());
1598             arr[0] = constCoords.swizzle(1, 0);
1599             arr[1] = constCoords.swizzle(2, 0);
1600             setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1601             setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1602             arr[0] = constCoords.swizzle(1, 1);
1603             arr[1] = constCoords.swizzle(3, 1);
1604             setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1605             setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1606             arr[0] = constCoords.swizzle(2, 1);
1607             arr[1] = constCoords.swizzle(2, 1);
1608             setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1609             setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1610             setUniform(gl, programID, "s[0].c", 0);
1611 
1612             setUniform(gl, programID, "s[1].a", constCoords.w());
1613             arr[0] = constCoords.swizzle(2, 0);
1614             arr[1] = constCoords.swizzle(2, 1);
1615             setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1616             setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1617             arr[0] = constCoords.swizzle(2, 2);
1618             arr[1] = constCoords.swizzle(3, 3);
1619             setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1620             setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1621             arr[0] = constCoords.swizzle(1, 0);
1622             arr[1] = constCoords.swizzle(3, 2);
1623             setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1624             setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1625             setUniform(gl, programID, "s[1].c", 1);
1626         },
1627         { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1628 
1629     UNIFORM_STRUCT_CASE(
1630         dynamic_loop_struct_array, "Struct array usage in dynamic loop", false,
1631         LineStream() << "${HEADER}"
1632                      << "uniform int ui_zero;"
1633                      << "uniform int ui_one;"
1634                      << "uniform int ui_two;"
1635                      << "uniform int ui_three;"
1636                      << ""
1637                      << "struct S {"
1638                      << "    mediump float   a;"
1639                      << "    mediump int     b;"
1640                      << "};"
1641                      << "uniform S s[3];"
1642                      << ""
1643                      << "void main (void)"
1644                      << "{"
1645                      << "    mediump float rgb[3];"
1646                      << "    int alpha = 0;"
1647                      << "    for (int i = 0; i < ui_three; i++)"
1648                      << "    {"
1649                      << "        rgb[i] = s[2-i].a;"
1650                      << "        alpha += s[i].b;"
1651                      << "    }"
1652                      << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1653                      << "    ${ASSIGN_POS}"
1654                      << "}",
1655         {
1656             setUniform(gl, programID, "s[0].a", constCoords.x());
1657             setUniform(gl, programID, "s[0].b", 0);
1658             setUniform(gl, programID, "s[1].a", constCoords.y());
1659             setUniform(gl, programID, "s[1].b", -1);
1660             setUniform(gl, programID, "s[2].a", constCoords.z());
1661             setUniform(gl, programID, "s[2].b", 2);
1662         },
1663         { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1664 
1665     UNIFORM_STRUCT_CASE(
1666         dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false,
1667         LineStream() << "${HEADER}"
1668                      << "uniform int ui_zero;"
1669                      << "uniform int ui_one;"
1670                      << "uniform int ui_two;"
1671                      << "uniform int ui_three;"
1672                      << "uniform mediump float uf_two;"
1673                      << "uniform mediump float uf_three;"
1674                      << "uniform mediump float uf_four;"
1675                      << "uniform mediump float uf_half;"
1676                      << "uniform mediump float uf_third;"
1677                      << "uniform mediump float uf_fourth;"
1678                      << "uniform mediump float uf_sixth;"
1679                      << ""
1680                      << "struct T {"
1681                      << "    mediump float   a;"
1682                      << "    mediump vec2    b[2];"
1683                      << "};"
1684                      << "struct S {"
1685                      << "    mediump float   a;"
1686                      << "    T               b[3];"
1687                      << "    int             c;"
1688                      << "};"
1689                      << "uniform S s[2];"
1690                      << ""
1691                      << "void main (void)"
1692                      << "{"
1693                      << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1694                      << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1695                      << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1696                      << "    mediump float a = 1.0;"
1697                      << "    for (int i = 0; i < ui_two; i++)"
1698                      << "    {"
1699                      << "        for (int j = 0; j < ui_three; j++)"
1700                      << "        {"
1701                      << "            r += s[0].b[j].b[i].y;"
1702                      << "            g += s[i].b[j].b[0].x;"
1703                      << "            b += s[i].b[j].b[1].x;"
1704                      << "            a *= s[i].b[j].a;"
1705                      << "        }"
1706                      << "    }"
1707                      << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1708                      << "    ${ASSIGN_POS}"
1709                      << "}",
1710         {
1711             tcu::Vec2 arr[2];
1712 
1713             setUniform(gl, programID, "s[0].a", constCoords.x());
1714             arr[0] = constCoords.swizzle(1, 0);
1715             arr[1] = constCoords.swizzle(2, 0);
1716             setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1717             setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1718             arr[0] = constCoords.swizzle(1, 1);
1719             arr[1] = constCoords.swizzle(3, 1);
1720             setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1721             setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1722             arr[0] = constCoords.swizzle(2, 1);
1723             arr[1] = constCoords.swizzle(2, 1);
1724             setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1725             setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1726             setUniform(gl, programID, "s[0].c", 0);
1727 
1728             setUniform(gl, programID, "s[1].a", constCoords.w());
1729             arr[0] = constCoords.swizzle(2, 0);
1730             arr[1] = constCoords.swizzle(2, 1);
1731             setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1732             setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1733             arr[0] = constCoords.swizzle(2, 2);
1734             arr[1] = constCoords.swizzle(3, 3);
1735             setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1736             setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1737             arr[0] = constCoords.swizzle(1, 0);
1738             arr[1] = constCoords.swizzle(3, 2);
1739             setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1740             setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1741             setUniform(gl, programID, "s[1].c", 1);
1742         },
1743         { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1744 
1745     UNIFORM_STRUCT_CASE(
1746         sampler, "Sampler in struct", true,
1747         LineStream() << "${HEADER}"
1748                      << "uniform int ui_one;"
1749                      << ""
1750                      << "struct S {"
1751                      << "    mediump float   a;"
1752                      << "    mediump vec3    b;"
1753                      << "    sampler2D       c;"
1754                      << "};"
1755                      << "uniform S s;"
1756                      << ""
1757                      << "void main (void)"
1758                      << "{"
1759                      << "    ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1760                      << "    ${ASSIGN_POS}"
1761                      << "}",
1762         {
1763             DE_UNREF(constCoords);
1764             setUniform(gl, programID, "s.a", 1.0f);
1765             setUniform(gl, programID, "s.b", tcu::Vec3(0.75f, 0.75f, 0.1f));
1766             setUniform(gl, programID, "s.c", TEXTURE_GRADIENT);
1767         },
1768         { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1769 
1770     UNIFORM_STRUCT_CASE(
1771         sampler_nested, "Sampler in nested struct", true,
1772         LineStream() << "${HEADER}"
1773                      << "uniform int ui_zero;"
1774                      << "uniform int ui_one;"
1775                      << ""
1776                      << "struct T {"
1777                      << "    sampler2D       a;"
1778                      << "    mediump vec2    b;"
1779                      << "};"
1780                      << "struct S {"
1781                      << "    mediump float   a;"
1782                      << "    T               b;"
1783                      << "    int             c;"
1784                      << "};"
1785                      << "uniform S s;"
1786                      << ""
1787                      << "void main (void)"
1788                      << "{"
1789                      << "    ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1790                      << "    ${ASSIGN_POS}"
1791                      << "}",
1792         {
1793             DE_UNREF(constCoords);
1794             setUniform(gl, programID, "s.a", 0.1f);
1795             setUniform(gl, programID, "s.b.a", TEXTURE_GRADIENT);
1796             setUniform(gl, programID, "s.b.b", tcu::Vec2(0.75f, 0.75f));
1797             setUniform(gl, programID, "s.c", 1);
1798         },
1799         { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1800 
1801     UNIFORM_STRUCT_CASE(
1802         sampler_array, "Sampler in struct array", true,
1803         LineStream() << "${HEADER}"
1804                      << "uniform int ui_one;"
1805                      << ""
1806                      << "struct S {"
1807                      << "    mediump float   a;"
1808                      << "    mediump vec3    b;"
1809                      << "    sampler2D       c;"
1810                      << "};"
1811                      << "uniform S s[2];"
1812                      << ""
1813                      << "void main (void)"
1814                      << "{"
1815                      << "    ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1816                      << "    ${ASSIGN_POS}"
1817                      << "}",
1818         {
1819             DE_UNREF(constCoords);
1820             setUniform(gl, programID, "s[0].a", 1.0f);
1821             setUniform(gl, programID, "s[0].b", tcu::Vec3(0.75f, 0.75f, 0.25f));
1822             setUniform(gl, programID, "s[0].c", 1);
1823             setUniform(gl, programID, "s[1].a", 0.0f);
1824             setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.1f));
1825             setUniform(gl, programID, "s[1].c", TEXTURE_GRADIENT);
1826         },
1827         { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1828 }
1829 
ShaderStructTests(Context & context,glu::GLSLVersion glslVersion)1830 ShaderStructTests::ShaderStructTests(Context &context, glu::GLSLVersion glslVersion)
1831     : TestCaseGroup(context, "struct", "Struct Tests")
1832     , m_glslVersion(glslVersion)
1833 {
1834 }
1835 
~ShaderStructTests(void)1836 ShaderStructTests::~ShaderStructTests(void)
1837 {
1838 }
1839 
init(void)1840 void ShaderStructTests::init(void)
1841 {
1842     addChild(new LocalStructTests(m_context, m_glslVersion));
1843     addChild(new UniformStructTests(m_context, m_glslVersion));
1844 }
1845 
1846 } // namespace deqp
1847