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