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