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