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