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