am ea702448: am d38c14ba: am 75e63782: am 523bdab6: am 4667bcc1: am f55476d8: Remove...
[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 };                                                                                                          \
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 { static void setUniforms (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY };           \
1195                         struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY };                                                                                                                                                          \
1196                         addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, TEXTURES, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC));            \
1197                         addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, TEXTURES, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC));         \
1198                 } while (deGetFalse())
1199
1200         UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false,
1201                 LineStream()
1202                 << "${HEADER}"
1203                 << "uniform int ui_one;"
1204                 << ""
1205                 << "struct S {"
1206                 << "    mediump float   a;"
1207                 << "    mediump vec3    b;"
1208                 << "    int                             c;"
1209                 << "};"
1210                 << "uniform S s;"
1211                 << ""
1212                 << "void main (void)"
1213                 << "{"
1214                 << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1215                 << "    ${ASSIGN_POS}"
1216                 << "}",
1217                 {
1218                         setUniform(gl, programID, "s.a", constCoords.x());
1219                         setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1220                         setUniform(gl, programID, "s.c", 1);
1221                 },
1222                 {
1223                         c.color.xyz() = c.constCoords.swizzle(0,1,2);
1224                 });
1225
1226         UNIFORM_STRUCT_CASE(nested, "Nested struct", false,
1227                 LineStream()
1228                 << "${HEADER}"
1229                 << "uniform int ui_zero;"
1230                 << "uniform int ui_one;"
1231                 << ""
1232                 << "struct T {"
1233                 << "    int                             a;"
1234                 << "    mediump vec2    b;"
1235                 << "};"
1236                 << "struct S {"
1237                 << "    mediump float   a;"
1238                 << "    T                               b;"
1239                 << "    int                             c;"
1240                 << "};"
1241                 << "uniform S s;"
1242                 << ""
1243                 << "void main (void)"
1244                 << "{"
1245                 << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1246                 << "    ${ASSIGN_POS}"
1247                 << "}",
1248                 {
1249                         setUniform(gl, programID, "s.a",        constCoords.x());
1250                         setUniform(gl, programID, "s.b.a",      0);
1251                         setUniform(gl, programID, "s.b.b",      constCoords.swizzle(1,2));
1252                         setUniform(gl, programID, "s.c",        1);
1253                 },
1254                 {
1255                         c.color.xyz() = c.constCoords.swizzle(0,1,2);
1256                 });
1257
1258         UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false,
1259                 LineStream()
1260                 << "${HEADER}"
1261                 << "uniform int ui_one;"
1262                 << ""
1263                 << "struct S {"
1264                 << "    mediump float   a;"
1265                 << "    mediump float   b[3];"
1266                 << "    int                             c;"
1267                 << "};"
1268                 << "uniform S s;"
1269                 << ""
1270                 << "void main (void)"
1271                 << "{"
1272                 << "    ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1273                 << "    ${ASSIGN_POS}"
1274                 << "}",
1275                 {
1276                         setUniform(gl, programID, "s.a",        constCoords.w());
1277                         setUniform(gl, programID, "s.c",        1);
1278
1279                         float b[3];
1280                         b[0] = constCoords.z();
1281                         b[1] = constCoords.y();
1282                         b[2] = constCoords.x();
1283                         setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1284                 },
1285                 {
1286                         c.color.xyz() = c.constCoords.swizzle(3,2,1);
1287                 });
1288
1289         UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", false,
1290                 LineStream()
1291                 << "${HEADER}"
1292                 << "uniform int ui_zero;"
1293                 << "uniform int ui_one;"
1294                 << "uniform int ui_two;"
1295                 << ""
1296                 << "struct S {"
1297                 << "    mediump float   a;"
1298                 << "    mediump float   b[3];"
1299                 << "    int                             c;"
1300                 << "};"
1301                 << "uniform S s;"
1302                 << ""
1303                 << "void main (void)"
1304                 << "{"
1305                 << "    ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1306                 << "    ${ASSIGN_POS}"
1307                 << "}",
1308                 {
1309                         setUniform(gl, programID, "s.a",        constCoords.w());
1310                         setUniform(gl, programID, "s.c",        1);
1311
1312                         float b[3];
1313                         b[0] = constCoords.z();
1314                         b[1] = constCoords.y();
1315                         b[2] = constCoords.x();
1316                         setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1317                 },
1318                 {
1319                         c.color.xyz() = c.constCoords.swizzle(1,2,0);
1320                 });
1321
1322         UNIFORM_STRUCT_CASE(struct_array, "Struct array", false,
1323                 LineStream()
1324                 << "${HEADER}"
1325                 << "uniform int ui_zero;"
1326                 << "uniform int ui_one;"
1327                 << "uniform int ui_two;"
1328                 << ""
1329                 << "struct S {"
1330                 << "    mediump float   a;"
1331                 << "    mediump int             b;"
1332                 << "};"
1333                 << "uniform S s[3];"
1334                 << ""
1335                 << "void main (void)"
1336                 << "{"
1337                 << "    ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1338                 << "    ${ASSIGN_POS}"
1339                 << "}",
1340                 {
1341                         setUniform(gl, programID, "s[0].a",     constCoords.x());
1342                         setUniform(gl, programID, "s[0].b",     0);
1343                         setUniform(gl, programID, "s[1].a",     constCoords.y());
1344                         setUniform(gl, programID, "s[1].b",     1);
1345                         setUniform(gl, programID, "s[2].a",     constCoords.z());
1346                         setUniform(gl, programID, "s[2].b",     2);
1347                 },
1348                 {
1349                         c.color.xyz() = c.constCoords.swizzle(2,1,0);
1350                 });
1351
1352         UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", false,
1353                 LineStream()
1354                 << "${HEADER}"
1355                 << "uniform int ui_zero;"
1356                 << "uniform int ui_one;"
1357                 << "uniform int ui_two;"
1358                 << ""
1359                 << "struct S {"
1360                 << "    mediump float   a;"
1361                 << "    mediump int             b;"
1362                 << "};"
1363                 << "uniform S s[3];"
1364                 << ""
1365                 << "void main (void)"
1366                 << "{"
1367                 << "    ${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);"
1368                 << "    ${ASSIGN_POS}"
1369                 << "}",
1370                 {
1371                         setUniform(gl, programID, "s[0].a",     constCoords.x());
1372                         setUniform(gl, programID, "s[0].b",     0);
1373                         setUniform(gl, programID, "s[1].a",     constCoords.y());
1374                         setUniform(gl, programID, "s[1].b",     1);
1375                         setUniform(gl, programID, "s[2].a",     constCoords.z());
1376                         setUniform(gl, programID, "s[2].b",     2);
1377                 },
1378                 {
1379                         c.color.xyz() = c.constCoords.swizzle(2,1,0);
1380                 });
1381
1382         UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", false,
1383                 LineStream()
1384                 << "${HEADER}"
1385                 << "struct T {"
1386                 << "    mediump float   a;"
1387                 << "    mediump vec2    b[2];"
1388                 << "};"
1389                 << "struct S {"
1390                 << "    mediump float   a;"
1391                 << "    T                               b[3];"
1392                 << "    int                             c;"
1393                 << "};"
1394                 << "uniform S s[2];"
1395                 << ""
1396                 << "void main (void)"
1397                 << "{"
1398                 << "    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"
1399                 << "    mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1400                 << "    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"
1401                 << "    mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1402                 << "    ${DST} = vec4(r, g, b, a);"
1403                 << "    ${ASSIGN_POS}"
1404                 << "}",
1405                 {
1406                         tcu::Vec2 arr[2];
1407
1408                         setUniform(gl, programID, "s[0].a",                     constCoords.x());
1409                         arr[0] = constCoords.swizzle(0,1);
1410                         arr[1] = constCoords.swizzle(2,3);
1411                         setUniform(gl, programID, "s[0].b[0].a",        0.5f);
1412                         setUniform(gl, programID, "s[0].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1413                         arr[0] = constCoords.swizzle(2,3);
1414                         arr[1] = constCoords.swizzle(0,1);
1415                         setUniform(gl, programID, "s[0].b[1].a",        1.0f/3.0f);
1416                         setUniform(gl, programID, "s[0].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1417                         arr[0] = constCoords.swizzle(0,2);
1418                         arr[1] = constCoords.swizzle(1,3);
1419                         setUniform(gl, programID, "s[0].b[2].a",        1.0f/4.0f);
1420                         setUniform(gl, programID, "s[0].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1421                         setUniform(gl, programID, "s[0].c",                     0);
1422
1423                         setUniform(gl, programID, "s[1].a",                     constCoords.w());
1424                         arr[0] = constCoords.swizzle(0,0);
1425                         arr[1] = constCoords.swizzle(1,1);
1426                         setUniform(gl, programID, "s[1].b[0].a",        2.0f);
1427                         setUniform(gl, programID, "s[1].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1428                         arr[0] = constCoords.swizzle(2,2);
1429                         arr[1] = constCoords.swizzle(3,3);
1430                         setUniform(gl, programID, "s[1].b[1].a",        3.0f);
1431                         setUniform(gl, programID, "s[1].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1432                         arr[0] = constCoords.swizzle(1,0);
1433                         arr[1] = constCoords.swizzle(3,2);
1434                         setUniform(gl, programID, "s[1].b[2].a",        4.0f);
1435                         setUniform(gl, programID, "s[1].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1436                         setUniform(gl, programID, "s[1].c",                     1);
1437                 },
1438                 {
1439                         c.color.xyz() = c.constCoords.swizzle(2,0,3);
1440                 });
1441
1442         UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false,
1443                 LineStream()
1444                 << "${HEADER}"
1445                 << "uniform int ui_zero;"
1446                 << "uniform int ui_one;"
1447                 << "uniform int ui_two;"
1448                 << ""
1449                 << "struct T {"
1450                 << "    mediump float   a;"
1451                 << "    mediump vec2    b[2];"
1452                 << "};"
1453                 << "struct S {"
1454                 << "    mediump float   a;"
1455                 << "    T                               b[3];"
1456                 << "    int                             c;"
1457                 << "};"
1458                 << "uniform S s[2];"
1459                 << ""
1460                 << "void main (void)"
1461                 << "{"
1462                 << "    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"
1463                 << "    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"
1464                 << "    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"
1465                 << "    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"
1466                 << "    ${DST} = vec4(r, g, b, a);"
1467                 << "    ${ASSIGN_POS}"
1468                 << "}",
1469                 {
1470                         tcu::Vec2 arr[2];
1471
1472                         setUniform(gl, programID, "s[0].a",                     constCoords.x());
1473                         arr[0] = constCoords.swizzle(0,1);
1474                         arr[1] = constCoords.swizzle(2,3);
1475                         setUniform(gl, programID, "s[0].b[0].a",        0.5f);
1476                         setUniform(gl, programID, "s[0].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1477                         arr[0] = constCoords.swizzle(2,3);
1478                         arr[1] = constCoords.swizzle(0,1);
1479                         setUniform(gl, programID, "s[0].b[1].a",        1.0f/3.0f);
1480                         setUniform(gl, programID, "s[0].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1481                         arr[0] = constCoords.swizzle(0,2);
1482                         arr[1] = constCoords.swizzle(1,3);
1483                         setUniform(gl, programID, "s[0].b[2].a",        1.0f/4.0f);
1484                         setUniform(gl, programID, "s[0].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1485                         setUniform(gl, programID, "s[0].c",                     0);
1486
1487                         setUniform(gl, programID, "s[1].a",                     constCoords.w());
1488                         arr[0] = constCoords.swizzle(0,0);
1489                         arr[1] = constCoords.swizzle(1,1);
1490                         setUniform(gl, programID, "s[1].b[0].a",        2.0f);
1491                         setUniform(gl, programID, "s[1].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1492                         arr[0] = constCoords.swizzle(2,2);
1493                         arr[1] = constCoords.swizzle(3,3);
1494                         setUniform(gl, programID, "s[1].b[1].a",        3.0f);
1495                         setUniform(gl, programID, "s[1].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1496                         arr[0] = constCoords.swizzle(1,0);
1497                         arr[1] = constCoords.swizzle(3,2);
1498                         setUniform(gl, programID, "s[1].b[2].a",        4.0f);
1499                         setUniform(gl, programID, "s[1].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1500                         setUniform(gl, programID, "s[1].c",                     1);
1501                 },
1502                 {
1503                         c.color.xyz() = c.constCoords.swizzle(2,0,3);
1504                 });
1505
1506         UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", false,
1507                 LineStream()
1508                 << "${HEADER}"
1509                 << "uniform int ui_zero;"
1510                 << "uniform int ui_one;"
1511                 << "uniform int ui_two;"
1512                 << ""
1513                 << "struct S {"
1514                 << "    mediump float   a;"
1515                 << "    mediump int             b;"
1516                 << "};"
1517                 << "uniform S s[3];"
1518                 << ""
1519                 << "void main (void)"
1520                 << "{"
1521                 << "    mediump float rgb[3];"
1522                 << "    int alpha = 0;"
1523                 << "    for (int i = 0; i < 3; i++)"
1524                 << "    {"
1525                 << "            rgb[i] = s[2-i].a;"
1526                 << "            alpha += s[i].b;"
1527                 << "    }"
1528                 << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1529                 << "    ${ASSIGN_POS}"
1530                 << "}",
1531                 {
1532                         setUniform(gl, programID, "s[0].a",     constCoords.x());
1533                         setUniform(gl, programID, "s[0].b",     0);
1534                         setUniform(gl, programID, "s[1].a",     constCoords.y());
1535                         setUniform(gl, programID, "s[1].b",     -1);
1536                         setUniform(gl, programID, "s[2].a",     constCoords.z());
1537                         setUniform(gl, programID, "s[2].b",     2);
1538                 },
1539                 {
1540                         c.color.xyz() = c.constCoords.swizzle(2,1,0);
1541                 });
1542
1543         UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", false,
1544                 LineStream()
1545                 << "${HEADER}"
1546                 << "uniform int ui_zero;"
1547                 << "uniform int ui_one;"
1548                 << "uniform int ui_two;"
1549                 << "uniform mediump float uf_two;"
1550                 << "uniform mediump float uf_three;"
1551                 << "uniform mediump float uf_four;"
1552                 << "uniform mediump float uf_half;"
1553                 << "uniform mediump float uf_third;"
1554                 << "uniform mediump float uf_fourth;"
1555                 << "uniform mediump float uf_sixth;"
1556                 << ""
1557                 << "struct T {"
1558                 << "    mediump float   a;"
1559                 << "    mediump vec2    b[2];"
1560                 << "};"
1561                 << "struct S {"
1562                 << "    mediump float   a;"
1563                 << "    T                               b[3];"
1564                 << "    int                             c;"
1565                 << "};"
1566                 << "uniform S s[2];"
1567                 << ""
1568                 << "void main (void)"
1569                 << "{"
1570                 << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1571                 << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1572                 << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1573                 << "    mediump float a = 1.0;"
1574                 << "    for (int i = 0; i < 2; i++)"
1575                 << "    {"
1576                 << "            for (int j = 0; j < 3; j++)"
1577                 << "            {"
1578                 << "                    r += s[0].b[j].b[i].y;"
1579                 << "                    g += s[i].b[j].b[0].x;"
1580                 << "                    b += s[i].b[j].b[1].x;"
1581                 << "                    a *= s[i].b[j].a;"
1582                 << "            }"
1583                 << "    }"
1584                 << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1585                 << "    ${ASSIGN_POS}"
1586                 << "}",
1587                 {
1588                         tcu::Vec2 arr[2];
1589
1590                         setUniform(gl, programID, "s[0].a",                     constCoords.x());
1591                         arr[0] = constCoords.swizzle(1,0);
1592                         arr[1] = constCoords.swizzle(2,0);
1593                         setUniform(gl, programID, "s[0].b[0].a",        0.5f);
1594                         setUniform(gl, programID, "s[0].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1595                         arr[0] = constCoords.swizzle(1,1);
1596                         arr[1] = constCoords.swizzle(3,1);
1597                         setUniform(gl, programID, "s[0].b[1].a",        1.0f/3.0f);
1598                         setUniform(gl, programID, "s[0].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1599                         arr[0] = constCoords.swizzle(2,1);
1600                         arr[1] = constCoords.swizzle(2,1);
1601                         setUniform(gl, programID, "s[0].b[2].a",        1.0f/4.0f);
1602                         setUniform(gl, programID, "s[0].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1603                         setUniform(gl, programID, "s[0].c",                     0);
1604
1605                         setUniform(gl, programID, "s[1].a",                     constCoords.w());
1606                         arr[0] = constCoords.swizzle(2,0);
1607                         arr[1] = constCoords.swizzle(2,1);
1608                         setUniform(gl, programID, "s[1].b[0].a",        2.0f);
1609                         setUniform(gl, programID, "s[1].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1610                         arr[0] = constCoords.swizzle(2,2);
1611                         arr[1] = constCoords.swizzle(3,3);
1612                         setUniform(gl, programID, "s[1].b[1].a",        3.0f);
1613                         setUniform(gl, programID, "s[1].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1614                         arr[0] = constCoords.swizzle(1,0);
1615                         arr[1] = constCoords.swizzle(3,2);
1616                         setUniform(gl, programID, "s[1].b[2].a",        4.0f);
1617                         setUniform(gl, programID, "s[1].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1618                         setUniform(gl, programID, "s[1].c",                     1);
1619                 },
1620                 {
1621                         c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1622                 });
1623
1624         UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", false,
1625                 LineStream()
1626                 << "${HEADER}"
1627                 << "uniform int ui_zero;"
1628                 << "uniform int ui_one;"
1629                 << "uniform int ui_two;"
1630                 << "uniform int ui_three;"
1631                 << ""
1632                 << "struct S {"
1633                 << "    mediump float   a;"
1634                 << "    mediump int             b;"
1635                 << "};"
1636                 << "uniform S s[3];"
1637                 << ""
1638                 << "void main (void)"
1639                 << "{"
1640                 << "    mediump float rgb[3];"
1641                 << "    int alpha = 0;"
1642                 << "    for (int i = 0; i < ui_three; i++)"
1643                 << "    {"
1644                 << "            rgb[i] = s[2-i].a;"
1645                 << "            alpha += s[i].b;"
1646                 << "    }"
1647                 << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1648                 << "    ${ASSIGN_POS}"
1649                 << "}",
1650                 {
1651                         setUniform(gl, programID, "s[0].a",     constCoords.x());
1652                         setUniform(gl, programID, "s[0].b",     0);
1653                         setUniform(gl, programID, "s[1].a",     constCoords.y());
1654                         setUniform(gl, programID, "s[1].b",     -1);
1655                         setUniform(gl, programID, "s[2].a",     constCoords.z());
1656                         setUniform(gl, programID, "s[2].b",     2);
1657                 },
1658                 {
1659                         c.color.xyz() = c.constCoords.swizzle(2,1,0);
1660                 });
1661
1662         UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false,
1663                 LineStream()
1664                 << "${HEADER}"
1665                 << "uniform int ui_zero;"
1666                 << "uniform int ui_one;"
1667                 << "uniform int ui_two;"
1668                 << "uniform int ui_three;"
1669                 << "uniform mediump float uf_two;"
1670                 << "uniform mediump float uf_three;"
1671                 << "uniform mediump float uf_four;"
1672                 << "uniform mediump float uf_half;"
1673                 << "uniform mediump float uf_third;"
1674                 << "uniform mediump float uf_fourth;"
1675                 << "uniform mediump float uf_sixth;"
1676                 << ""
1677                 << "struct T {"
1678                 << "    mediump float   a;"
1679                 << "    mediump vec2    b[2];"
1680                 << "};"
1681                 << "struct S {"
1682                 << "    mediump float   a;"
1683                 << "    T                               b[3];"
1684                 << "    int                             c;"
1685                 << "};"
1686                 << "uniform S s[2];"
1687                 << ""
1688                 << "void main (void)"
1689                 << "{"
1690                 << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1691                 << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1692                 << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1693                 << "    mediump float a = 1.0;"
1694                 << "    for (int i = 0; i < ui_two; i++)"
1695                 << "    {"
1696                 << "            for (int j = 0; j < ui_three; j++)"
1697                 << "            {"
1698                 << "                    r += s[0].b[j].b[i].y;"
1699                 << "                    g += s[i].b[j].b[0].x;"
1700                 << "                    b += s[i].b[j].b[1].x;"
1701                 << "                    a *= s[i].b[j].a;"
1702                 << "            }"
1703                 << "    }"
1704                 << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1705                 << "    ${ASSIGN_POS}"
1706                 << "}",
1707                 {
1708                         tcu::Vec2 arr[2];
1709
1710                         setUniform(gl, programID, "s[0].a",                     constCoords.x());
1711                         arr[0] = constCoords.swizzle(1,0);
1712                         arr[1] = constCoords.swizzle(2,0);
1713                         setUniform(gl, programID, "s[0].b[0].a",        0.5f);
1714                         setUniform(gl, programID, "s[0].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1715                         arr[0] = constCoords.swizzle(1,1);
1716                         arr[1] = constCoords.swizzle(3,1);
1717                         setUniform(gl, programID, "s[0].b[1].a",        1.0f/3.0f);
1718                         setUniform(gl, programID, "s[0].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1719                         arr[0] = constCoords.swizzle(2,1);
1720                         arr[1] = constCoords.swizzle(2,1);
1721                         setUniform(gl, programID, "s[0].b[2].a",        1.0f/4.0f);
1722                         setUniform(gl, programID, "s[0].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1723                         setUniform(gl, programID, "s[0].c",                     0);
1724
1725                         setUniform(gl, programID, "s[1].a",                     constCoords.w());
1726                         arr[0] = constCoords.swizzle(2,0);
1727                         arr[1] = constCoords.swizzle(2,1);
1728                         setUniform(gl, programID, "s[1].b[0].a",        2.0f);
1729                         setUniform(gl, programID, "s[1].b[0].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1730                         arr[0] = constCoords.swizzle(2,2);
1731                         arr[1] = constCoords.swizzle(3,3);
1732                         setUniform(gl, programID, "s[1].b[1].a",        3.0f);
1733                         setUniform(gl, programID, "s[1].b[1].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1734                         arr[0] = constCoords.swizzle(1,0);
1735                         arr[1] = constCoords.swizzle(3,2);
1736                         setUniform(gl, programID, "s[1].b[2].a",        4.0f);
1737                         setUniform(gl, programID, "s[1].b[2].b",        &arr[0], DE_LENGTH_OF_ARRAY(arr));
1738                         setUniform(gl, programID, "s[1].c",                     1);
1739                 },
1740                 {
1741                         c.color.xyz() = (c.constCoords.swizzle(0,1,2) + c.constCoords.swizzle(1,2,3)) * 0.5f;
1742                 });
1743
1744         UNIFORM_STRUCT_CASE(sampler, "Sampler in struct", true,
1745                 LineStream()
1746                 << "${HEADER}"
1747                 << "uniform int ui_one;"
1748                 << ""
1749                 << "struct S {"
1750                 << "    mediump float   a;"
1751                 << "    mediump vec3    b;"
1752                 << "    sampler2D               c;"
1753                 << "};"
1754                 << "uniform S s;"
1755                 << ""
1756                 << "void main (void)"
1757                 << "{"
1758                 << "    ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1759                 << "    ${ASSIGN_POS}"
1760                 << "}",
1761                 {
1762                         DE_UNREF(constCoords);
1763                         setUniform(gl, programID, "s.a", 1.0f);
1764                         setUniform(gl, programID, "s.b", tcu::Vec3(0.25f, 0.25f, 0.5f));
1765                         setUniform(gl, programID, "s.c", 0);
1766                 },
1767                 {
1768                         c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1769                 });
1770
1771         UNIFORM_STRUCT_CASE(sampler_nested, "Sampler in nested struct", true,
1772                 LineStream()
1773                 << "${HEADER}"
1774                 << "uniform int ui_zero;"
1775                 << "uniform int ui_one;"
1776                 << ""
1777                 << "struct T {"
1778                 << "    sampler2D               a;"
1779                 << "    mediump vec2    b;"
1780                 << "};"
1781                 << "struct S {"
1782                 << "    mediump float   a;"
1783                 << "    T                               b;"
1784                 << "    int                             c;"
1785                 << "};"
1786                 << "uniform S s;"
1787                 << ""
1788                 << "void main (void)"
1789                 << "{"
1790                 << "    ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1791                 << "    ${ASSIGN_POS}"
1792                 << "}",
1793                 {
1794                         DE_UNREF(constCoords);
1795                         setUniform(gl, programID, "s.a",        0.5f);
1796                         setUniform(gl, programID, "s.b.a",      0);
1797                         setUniform(gl, programID, "s.b.b",      tcu::Vec2(0.25f, 0.25f));
1798                         setUniform(gl, programID, "s.c",        1);
1799                 },
1800                 {
1801                         c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1802                 });
1803
1804         UNIFORM_STRUCT_CASE(sampler_array, "Sampler in struct array", true,
1805                 LineStream()
1806                 << "${HEADER}"
1807                 << "uniform int ui_one;"
1808                 << ""
1809                 << "struct S {"
1810                 << "    mediump float   a;"
1811                 << "    mediump vec3    b;"
1812                 << "    sampler2D               c;"
1813                 << "};"
1814                 << "uniform S s[2];"
1815                 << ""
1816                 << "void main (void)"
1817                 << "{"
1818                 << "    ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1819                 << "    ${ASSIGN_POS}"
1820                 << "}",
1821                 {
1822                         DE_UNREF(constCoords);
1823                         setUniform(gl, programID, "s[0].a", 1.0f);
1824                         setUniform(gl, programID, "s[0].b", tcu::Vec3(0.25f, 0.25f, 0.25f));
1825                         setUniform(gl, programID, "s[0].c", 1);
1826                         setUniform(gl, programID, "s[1].a", 0.0f);
1827                         setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.5f));
1828                         setUniform(gl, programID, "s[1].c", 0);
1829                 },
1830                 {
1831                         c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
1832                 });
1833
1834         UNIFORM_STRUCT_CASE(equal, "Struct equality", false,
1835                 LineStream()
1836                 << "${HEADER}"
1837                 << "uniform mediump float uf_one;"
1838                 << "uniform int ui_two;"
1839                 << ""
1840                 << "struct S {"
1841                 << "    mediump float   a;"
1842                 << "    mediump vec3    b;"
1843                 << "    int                             c;"
1844                 << "};"
1845                 << "uniform S a;"
1846                 << "uniform S b;"
1847                 << "uniform S c;"
1848                 << ""
1849                 << "void main (void)"
1850                 << "{"
1851                 << "    S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1852                 << "    ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1853                 << "    if (a == b) ${DST}.x = 1.0;"
1854                 << "    if (a == c) ${DST}.y = 1.0;"
1855                 << "    if (a == d) ${DST}.z = 1.0;"
1856                 << "    ${ASSIGN_POS}"
1857                 << "}",
1858                 {
1859                         DE_UNREF(constCoords);
1860                         setUniform(gl, programID, "a.a", 1.0f);
1861                         setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1862                         setUniform(gl, programID, "a.c", 2);
1863                         setUniform(gl, programID, "b.a", 1.0f);
1864                         setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1865                         setUniform(gl, programID, "b.c", 2);
1866                         setUniform(gl, programID, "c.a", 1.0f);
1867                         setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1868                         setUniform(gl, programID, "c.c", 2);
1869                 },
1870                 {
1871                         c.color.xy() = tcu::Vec2(1.0f, 0.0f);
1872                         if (deFloatFloor(c.coords[1]+1.0f) == deFloatFloor(1.1f))
1873                                 c.color.z() = 1.0f;
1874                 });
1875
1876         UNIFORM_STRUCT_CASE(not_equal, "Struct equality", false,
1877                 LineStream()
1878                 << "${HEADER}"
1879                 << "uniform mediump float uf_one;"
1880                 << "uniform int ui_two;"
1881                 << ""
1882                 << "struct S {"
1883                 << "    mediump float   a;"
1884                 << "    mediump vec3    b;"
1885                 << "    int                             c;"
1886                 << "};"
1887                 << "uniform S a;"
1888                 << "uniform S b;"
1889                 << "uniform S c;"
1890                 << ""
1891                 << "void main (void)"
1892                 << "{"
1893                 << "    S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);"
1894                 << "    ${DST} = vec4(0.0, 0.0, 0.0, 1.0);"
1895                 << "    if (a != b) ${DST}.x = 1.0;"
1896                 << "    if (a != c) ${DST}.y = 1.0;"
1897                 << "    if (a != d) ${DST}.z = 1.0;"
1898                 << "    ${ASSIGN_POS}"
1899                 << "}",
1900                 {
1901                         DE_UNREF(constCoords);
1902                         setUniform(gl, programID, "a.a", 1.0f);
1903                         setUniform(gl, programID, "a.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1904                         setUniform(gl, programID, "a.c", 2);
1905                         setUniform(gl, programID, "b.a", 1.0f);
1906                         setUniform(gl, programID, "b.b", tcu::Vec3(0.0f, 1.0f, 2.0f));
1907                         setUniform(gl, programID, "b.c", 2);
1908                         setUniform(gl, programID, "c.a", 1.0f);
1909                         setUniform(gl, programID, "c.b", tcu::Vec3(0.0f, 1.1f, 2.0f));
1910                         setUniform(gl, programID, "c.c", 2);
1911                 },
1912                 {
1913                         c.color.xy() = tcu::Vec2(0.0f, 1.0f);
1914                         if (deFloatFloor(c.coords[1]+1.0f) != deFloatFloor(1.1f))
1915                                 c.color.z() = 1.0f;
1916                 });
1917 }
1918
1919 ShaderStructTests::ShaderStructTests (Context& context)
1920         : TestCaseGroup(context, "struct", "Struct Tests")
1921 {
1922 }
1923
1924 ShaderStructTests::~ShaderStructTests (void)
1925 {
1926 }
1927
1928 void ShaderStructTests::init (void)
1929 {
1930         addChild(new LocalStructTests(m_context));
1931         addChild(new UniformStructTests(m_context));
1932 }
1933
1934 } // Functional
1935 } // gles3
1936 } // deqp