Always apply flat qualifier to double inputs, same as int/uint
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcShaderStructTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief Shader struct tests.
23  */ /*-------------------------------------------------------------------*/
24
25 #include "glcShaderStructTests.hpp"
26 #include "glcShaderRenderCase.hpp"
27 #include "gluTexture.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuStringTemplate.hpp"
31 #include "tcuTextureUtil.hpp"
32
33 using tcu::StringTemplate;
34
35 using std::string;
36 using std::vector;
37 using std::ostringstream;
38
39 using namespace glu;
40
41 namespace deqp
42 {
43
44 enum
45 {
46         TEXTURE_GRADIENT = 0 //!< Unit index for gradient texture
47 };
48
49 typedef void (*SetupUniformsFunc)(const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords);
50
51 class ShaderStructCase : public ShaderRenderCase
52 {
53 public:
54         ShaderStructCase(Context& context, const char* name, const char* description, bool isVertexCase, bool usesTextures,
55                                          ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource,
56                                          const char* fragShaderSource);
57         ~ShaderStructCase(void);
58
59         void init(void);
60         void deinit(void);
61
62         virtual void setupUniforms(deUint32 programID, const tcu::Vec4& constCoords);
63
64 private:
65         ShaderStructCase(const ShaderStructCase&);
66         ShaderStructCase& operator=(const ShaderStructCase&);
67
68         SetupUniformsFunc m_setupUniforms;
69         bool                      m_usesTexture;
70
71         glu::Texture2D* m_gradientTexture;
72 };
73
74 ShaderStructCase::ShaderStructCase(Context& context, const char* name, const char* description, bool isVertexCase,
75                                                                    bool usesTextures, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc,
76                                                                    const char* vertShaderSource, const char* fragShaderSource)
77         : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
78                                            description, isVertexCase, evalFunc)
79         , m_setupUniforms(setupUniformsFunc)
80         , m_usesTexture(usesTextures)
81         , m_gradientTexture(DE_NULL)
82 {
83         m_vertShaderSource = vertShaderSource;
84         m_fragShaderSource = fragShaderSource;
85 }
86
87 ShaderStructCase::~ShaderStructCase(void)
88 {
89 }
90
91 void ShaderStructCase::init(void)
92 {
93         if (m_usesTexture)
94         {
95                 m_gradientTexture = new glu::Texture2D(m_renderCtx, GL_RGBA8, 128, 128);
96
97                 m_gradientTexture->getRefTexture().allocLevel(0);
98                 tcu::fillWithComponentGradients(m_gradientTexture->getRefTexture().getLevel(0), tcu::Vec4(0.0f),
99                                                                                 tcu::Vec4(1.0f));
100                 m_gradientTexture->upload();
101
102                 m_textures.push_back(TextureBinding(
103                         m_gradientTexture, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
104                                                                                         tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR)));
105                 DE_ASSERT(m_textures.size() == 1);
106         }
107         ShaderRenderCase::init();
108 }
109
110 void ShaderStructCase::deinit(void)
111 {
112         if (m_usesTexture)
113         {
114                 delete m_gradientTexture;
115         }
116         ShaderRenderCase::deinit();
117 }
118
119 void ShaderStructCase::setupUniforms(deUint32 programID, const tcu::Vec4& constCoords)
120 {
121         ShaderRenderCase::setupUniforms(programID, constCoords);
122         if (m_setupUniforms)
123                 m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
124 }
125
126 static ShaderStructCase* createStructCase(Context& context, const char* name, const char* description,
127                                                                                   glu::GLSLVersion glslVersion, bool isVertexCase, bool usesTextures,
128                                                                                   ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms,
129                                                                                   const LineStream& shaderSrc)
130 {
131         const std::string versionDecl = glu::getGLSLVersionDeclaration(glslVersion);
132
133         const std::string defaultVertSrc = versionDecl + "\n"
134                                                                                                          "in highp vec4 a_position;\n"
135                                                                                                          "in highp vec4 a_coords;\n"
136                                                                                                          "out mediump vec4 v_coords;\n\n"
137                                                                                                          "void main (void)\n"
138                                                                                                          "{\n"
139                                                                                                          "   v_coords = a_coords;\n"
140                                                                                                          "   gl_Position = a_position;\n"
141                                                                                                          "}\n";
142         const std::string defaultFragSrc = versionDecl + "\n"
143                                                                                                          "in mediump vec4 v_color;\n"
144                                                                                                          "layout(location = 0) out mediump vec4 o_color;\n\n"
145                                                                                                          "void main (void)\n"
146                                                                                                          "{\n"
147                                                                                                          "   o_color = v_color;\n"
148                                                                                                          "}\n";
149
150         // Fill in specialization parameters.
151         std::map<std::string, std::string> spParams;
152         if (isVertexCase)
153         {
154                 spParams["HEADER"] = versionDecl + "\n"
155                                                                                    "in highp vec4 a_position;\n"
156                                                                                    "in highp vec4 a_coords;\n"
157                                                                                    "out mediump vec4 v_color;";
158                 spParams["COORDS"]       = "a_coords";
159                 spParams["DST"]            = "v_color";
160                 spParams["ASSIGN_POS"] = "gl_Position = a_position;";
161         }
162         else
163         {
164                 spParams["HEADER"] = versionDecl + "\n"
165                                                                                    "in mediump vec4 v_coords;\n"
166                                                                                    "layout(location = 0) out mediump vec4 o_color;";
167                 spParams["COORDS"]       = "v_coords";
168                 spParams["DST"]            = "o_color";
169                 spParams["ASSIGN_POS"] = "";
170         }
171
172         if (isVertexCase)
173                 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
174                                                                         StringTemplate(shaderSrc.str()).specialize(spParams).c_str(),
175                                                                         defaultFragSrc.c_str());
176         else
177                 return new ShaderStructCase(context, name, description, isVertexCase, usesTextures, evalFunc, setupUniforms,
178                                                                         defaultVertSrc.c_str(),
179                                                                         StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
180 }
181
182 class LocalStructTests : public TestCaseGroup
183 {
184 public:
185         LocalStructTests(Context& context, glu::GLSLVersion glslVersion)
186                 : TestCaseGroup(context, "local", "Local structs"), m_glslVersion(glslVersion)
187         {
188         }
189
190         ~LocalStructTests(void)
191         {
192         }
193
194         virtual void init(void);
195
196 private:
197         glu::GLSLVersion m_glslVersion;
198 };
199
200 void LocalStructTests::init(void)
201 {
202 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY)                                  \
203         do                                                                                                    \
204         {                                                                                                     \
205                 struct Eval_##NAME                                                                                \
206                 {                                                                                                 \
207                         static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY                                         \
208                 };                                                                                                \
209                 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, false,    \
210                                                                   &Eval_##NAME::eval, DE_NULL, SHADER_SRC));                              \
211                 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, false, \
212                                                                   &Eval_##NAME::eval, DE_NULL, SHADER_SRC));                              \
213         } while (deGetFalse())
214
215         LOCAL_STRUCT_CASE(basic, "Basic struct usage",
216                                           LineStream() << "${HEADER}"
217                                                                    << "uniform int ui_one;"
218                                                                    << ""
219                                                                    << "struct S {"
220                                                                    << "    mediump float   a;"
221                                                                    << "    mediump vec3    b;"
222                                                                    << "    int             c;"
223                                                                    << "};"
224                                                                    << ""
225                                                                    << "void main (void)"
226                                                                    << "{"
227                                                                    << "    S s = S(${COORDS}.x, vec3(0.0), ui_one);"
228                                                                    << "    s.b = ${COORDS}.yzw;"
229                                                                    << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
230                                                                    << "    ${ASSIGN_POS}"
231                                                                    << "}",
232                                           { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
233
234         LOCAL_STRUCT_CASE(nested, "Nested struct",
235                                           LineStream() << "${HEADER}"
236                                                                    << "uniform int ui_zero;"
237                                                                    << "uniform int ui_one;"
238                                                                    << ""
239                                                                    << "struct T {"
240                                                                    << "    int             a;"
241                                                                    << "    mediump vec2    b;"
242                                                                    << "};"
243                                                                    << "struct S {"
244                                                                    << "    mediump float   a;"
245                                                                    << "    T               b;"
246                                                                    << "    int             c;"
247                                                                    << "};"
248                                                                    << ""
249                                                                    << "void main (void)"
250                                                                    << "{"
251                                                                    << "    S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
252                                                                    << "    s.b = T(ui_zero, ${COORDS}.yz);"
253                                                                    << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
254                                                                    << "    ${ASSIGN_POS}"
255                                                                    << "}",
256                                           { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
257
258         LOCAL_STRUCT_CASE(array_member, "Struct with array member",
259                                           LineStream() << "${HEADER}"
260                                                                    << "uniform int ui_one;"
261                                                                    << ""
262                                                                    << "struct S {"
263                                                                    << "    mediump float   a;"
264                                                                    << "    mediump float   b[3];"
265                                                                    << "    int             c;"
266                                                                    << "};"
267                                                                    << ""
268                                                                    << "void main (void)"
269                                                                    << "{"
270                                                                    << "    S s;"
271                                                                    << "    s.a = ${COORDS}.w;"
272                                                                    << "    s.c = ui_one;"
273                                                                    << "    s.b[0] = ${COORDS}.z;"
274                                                                    << "    s.b[1] = ${COORDS}.y;"
275                                                                    << "    s.b[2] = ${COORDS}.x;"
276                                                                    << "    ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
277                                                                    << "    ${ASSIGN_POS}"
278                                                                    << "}",
279                                           { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
280
281         LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing",
282                                           LineStream() << "${HEADER}"
283                                                                    << "uniform int ui_zero;"
284                                                                    << "uniform int ui_one;"
285                                                                    << "uniform int ui_two;"
286                                                                    << ""
287                                                                    << "struct S {"
288                                                                    << "    mediump float   a;"
289                                                                    << "    mediump float   b[3];"
290                                                                    << "    int             c;"
291                                                                    << "};"
292                                                                    << ""
293                                                                    << "void main (void)"
294                                                                    << "{"
295                                                                    << "    S s;"
296                                                                    << "    s.a = ${COORDS}.w;"
297                                                                    << "    s.c = ui_one;"
298                                                                    << "    s.b[0] = ${COORDS}.z;"
299                                                                    << "    s.b[1] = ${COORDS}.y;"
300                                                                    << "    s.b[2] = ${COORDS}.x;"
301                                                                    << "    ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
302                                                                    << "    ${ASSIGN_POS}"
303                                                                    << "}",
304                                           { c.color.xyz() = c.coords.swizzle(1, 2, 0); });
305
306         LOCAL_STRUCT_CASE(struct_array, "Struct array",
307                                           LineStream() << "${HEADER}"
308                                                                    << "uniform int ui_zero;"
309                                                                    << "uniform int ui_one;"
310                                                                    << "uniform int ui_two;"
311                                                                    << ""
312                                                                    << "struct S {"
313                                                                    << "    mediump float   a;"
314                                                                    << "    mediump int     b;"
315                                                                    << "};"
316                                                                    << ""
317                                                                    << "void main (void)"
318                                                                    << "{"
319                                                                    << "    S s[3];"
320                                                                    << "    s[0] = S(${COORDS}.x, ui_zero);"
321                                                                    << "    s[1].a = ${COORDS}.y;"
322                                                                    << "    s[1].b = ui_one;"
323                                                                    << "    s[2] = S(${COORDS}.z, ui_two);"
324                                                                    << "    ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
325                                                                    << "    ${ASSIGN_POS}"
326                                                                    << "}",
327                                           { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
328
329         LOCAL_STRUCT_CASE(
330                 struct_array_dynamic_index, "Struct array with dynamic indexing",
331                 LineStream()
332                         << "${HEADER}"
333                         << "uniform int ui_zero;"
334                         << "uniform int ui_one;"
335                         << "uniform int ui_two;"
336                         << ""
337                         << "struct S {"
338                         << "    mediump float   a;"
339                         << "    mediump int     b;"
340                         << "};"
341                         << ""
342                         << "void main (void)"
343                         << "{"
344                         << "    S s[3];"
345                         << "    s[0] = S(${COORDS}.x, ui_zero);"
346                         << "    s[1].a = ${COORDS}.y;"
347                         << "    s[1].b = ui_one;"
348                         << "    s[2] = S(${COORDS}.z, ui_two);"
349                         << "    ${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);"
350                         << "    ${ASSIGN_POS}"
351                         << "}",
352                 { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
353
354         LOCAL_STRUCT_CASE(
355                 nested_struct_array, "Nested struct array",
356                 LineStream() << "${HEADER}"
357                                          << "uniform int ui_zero;"
358                                          << "uniform int ui_one;"
359                                          << "uniform int ui_two;"
360                                          << "uniform mediump float uf_two;"
361                                          << "uniform mediump float uf_three;"
362                                          << "uniform mediump float uf_four;"
363                                          << "uniform mediump float uf_half;"
364                                          << "uniform mediump float uf_third;"
365                                          << "uniform mediump float uf_fourth;"
366                                          << ""
367                                          << "struct T {"
368                                          << "    mediump float   a;"
369                                          << "    mediump vec2    b[2];"
370                                          << "};"
371                                          << "struct S {"
372                                          << "    mediump float   a;"
373                                          << "    T               b[3];"
374                                          << "    int             c;"
375                                          << "};"
376                                          << ""
377                                          << "void main (void)"
378                                          << "{"
379                                          << "    S s[2];"
380                                          << ""
381                                          << "    // S[0]"
382                                          << "    s[0].a         = ${COORDS}.x;"
383                                          << "    s[0].b[0].a    = uf_half;"
384                                          << "    s[0].b[0].b[0] = ${COORDS}.xy;"
385                                          << "    s[0].b[0].b[1] = ${COORDS}.zw;"
386                                          << "    s[0].b[1].a    = uf_third;"
387                                          << "    s[0].b[1].b[0] = ${COORDS}.zw;"
388                                          << "    s[0].b[1].b[1] = ${COORDS}.xy;"
389                                          << "    s[0].b[2].a    = uf_fourth;"
390                                          << "    s[0].b[2].b[0] = ${COORDS}.xz;"
391                                          << "    s[0].b[2].b[1] = ${COORDS}.yw;"
392                                          << "    s[0].c         = ui_zero;"
393                                          << ""
394                                          << "    // S[1]"
395                                          << "    s[1].a         = ${COORDS}.w;"
396                                          << "    s[1].b[0].a    = uf_two;"
397                                          << "    s[1].b[0].b[0] = ${COORDS}.xx;"
398                                          << "    s[1].b[0].b[1] = ${COORDS}.yy;"
399                                          << "    s[1].b[1].a    = uf_three;"
400                                          << "    s[1].b[1].b[0] = ${COORDS}.zz;"
401                                          << "    s[1].b[1].b[1] = ${COORDS}.ww;"
402                                          << "    s[1].b[2].a    = uf_four;"
403                                          << "    s[1].b[2].b[0] = ${COORDS}.yx;"
404                                          << "    s[1].b[2].b[1] = ${COORDS}.wz;"
405                                          << "    s[1].c         = ui_one;"
406                                          << ""
407                                          << "    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"
408                                          << "    mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
409                                          << "    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 "
410                                                 "+ w) * 0.333"
411                                          << "    mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
412                                          << "    ${DST} = vec4(r, g, b, a);"
413                                          << "    ${ASSIGN_POS}"
414                                          << "}",
415                 { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
416
417         LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing",
418                                           LineStream() << "${HEADER}"
419                                                                    << "uniform int ui_zero;"
420                                                                    << "uniform int ui_one;"
421                                                                    << "uniform int ui_two;"
422                                                                    << "uniform mediump float uf_two;"
423                                                                    << "uniform mediump float uf_three;"
424                                                                    << "uniform mediump float uf_four;"
425                                                                    << "uniform mediump float uf_half;"
426                                                                    << "uniform mediump float uf_third;"
427                                                                    << "uniform mediump float uf_fourth;"
428                                                                    << ""
429                                                                    << "struct T {"
430                                                                    << "    mediump float   a;"
431                                                                    << "    mediump vec2    b[2];"
432                                                                    << "};"
433                                                                    << "struct S {"
434                                                                    << "    mediump float   a;"
435                                                                    << "    T               b[3];"
436                                                                    << "    int             c;"
437                                                                    << "};"
438                                                                    << ""
439                                                                    << "void main (void)"
440                                                                    << "{"
441                                                                    << "    S s[2];"
442                                                                    << ""
443                                                                    << "    // S[0]"
444                                                                    << "    s[0].a         = ${COORDS}.x;"
445                                                                    << "    s[0].b[0].a    = uf_half;"
446                                                                    << "    s[0].b[0].b[0] = ${COORDS}.xy;"
447                                                                    << "    s[0].b[0].b[1] = ${COORDS}.zw;"
448                                                                    << "    s[0].b[1].a    = uf_third;"
449                                                                    << "    s[0].b[1].b[0] = ${COORDS}.zw;"
450                                                                    << "    s[0].b[1].b[1] = ${COORDS}.xy;"
451                                                                    << "    s[0].b[2].a    = uf_fourth;"
452                                                                    << "    s[0].b[2].b[0] = ${COORDS}.xz;"
453                                                                    << "    s[0].b[2].b[1] = ${COORDS}.yw;"
454                                                                    << "    s[0].c         = ui_zero;"
455                                                                    << ""
456                                                                    << "    // S[1]"
457                                                                    << "    s[1].a         = ${COORDS}.w;"
458                                                                    << "    s[1].b[0].a    = uf_two;"
459                                                                    << "    s[1].b[0].b[0] = ${COORDS}.xx;"
460                                                                    << "    s[1].b[0].b[1] = ${COORDS}.yy;"
461                                                                    << "    s[1].b[1].a    = uf_three;"
462                                                                    << "    s[1].b[1].b[0] = ${COORDS}.zz;"
463                                                                    << "    s[1].b[1].b[1] = ${COORDS}.ww;"
464                                                                    << "    s[1].b[2].a    = uf_four;"
465                                                                    << "    s[1].b[2].b[0] = ${COORDS}.yx;"
466                                                                    << "    s[1].b[2].b[1] = ${COORDS}.wz;"
467                                                                    << "    s[1].c         = ui_one;"
468                                                                    << ""
469                                                                    << "    mediump float r = (s[0].b[ui_one].b[ui_one-1].x + "
470                                                                           "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 * "
472                                                                           "s[ui_one].b[2].a; // x * 0.25 * 4"
473                                                                    << "    mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + "
474                                                                           "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + "
475                                                                           "w + w) * 0.333"
476                                                                    << "    mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - "
477                                                                           "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
478                                                                    << "    ${DST} = vec4(r, g, b, a);"
479                                                                    << "    ${ASSIGN_POS}"
480                                                                    << "}",
481                                           { c.color.xyz() = c.coords.swizzle(2, 0, 3); });
482
483         LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter",
484                                           LineStream() << "${HEADER}"
485                                                                    << "uniform int ui_one;"
486                                                                    << ""
487                                                                    << "struct S {"
488                                                                    << "    mediump float   a;"
489                                                                    << "    mediump vec3    b;"
490                                                                    << "    int             c;"
491                                                                    << "};"
492                                                                    << ""
493                                                                    << "mediump vec4 myFunc (S s)"
494                                                                    << "{"
495                                                                    << "    return vec4(s.a, s.b.x, s.b.y, s.c);"
496                                                                    << "}"
497                                                                    << ""
498                                                                    << "void main (void)"
499                                                                    << "{"
500                                                                    << "    S s = S(${COORDS}.x, vec3(0.0), ui_one);"
501                                                                    << "    s.b = ${COORDS}.yzw;"
502                                                                    << "    ${DST} = myFunc(s);"
503                                                                    << "    ${ASSIGN_POS}"
504                                                                    << "}",
505                                           { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
506
507         LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter",
508                                           LineStream() << "${HEADER}"
509                                                                    << "uniform int ui_zero;"
510                                                                    << "uniform int ui_one;"
511                                                                    << ""
512                                                                    << "struct T {"
513                                                                    << "    int             a;"
514                                                                    << "    mediump vec2    b;"
515                                                                    << "};"
516                                                                    << "struct S {"
517                                                                    << "    mediump float   a;"
518                                                                    << "    T               b;"
519                                                                    << "    int             c;"
520                                                                    << "};"
521                                                                    << ""
522                                                                    << "mediump vec4 myFunc (S s)"
523                                                                    << "{"
524                                                                    << "    return vec4(s.a, s.b.b, s.b.a + s.c);"
525                                                                    << "}"
526                                                                    << ""
527                                                                    << "void main (void)"
528                                                                    << "{"
529                                                                    << "    S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
530                                                                    << "    s.b = T(ui_zero, ${COORDS}.yz);"
531                                                                    << "    ${DST} = myFunc(s);"
532                                                                    << "    ${ASSIGN_POS}"
533                                                                    << "}",
534                                           { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
535
536         LOCAL_STRUCT_CASE(return, "Struct as a return value",
537                                                         LineStream() << "${HEADER}"
538                                                                                  << "uniform int ui_one;"
539                                                                                  << ""
540                                                                                  << "struct S {"
541                                                                                  << "    mediump float   a;"
542                                                                                  << "    mediump vec3    b;"
543                                                                                  << "    int             c;"
544                                                                                  << "};"
545                                                                                  << ""
546                                                                                  << "S myFunc (void)"
547                                                                                  << "{"
548                                                                                  << "    S s = S(${COORDS}.x, vec3(0.0), ui_one);"
549                                                                                  << "    s.b = ${COORDS}.yzw;"
550                                                                                  << "    return s;"
551                                                                                  << "}"
552                                                                                  << ""
553                                                                                  << "void main (void)"
554                                                                                  << "{"
555                                                                                  << "    S s = myFunc();"
556                                                                                  << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
557                                                                                  << "    ${ASSIGN_POS}"
558                                                                                  << "}",
559                                                         { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
560
561         LOCAL_STRUCT_CASE(return_nested, "Nested struct",
562                                           LineStream() << "${HEADER}"
563                                                                    << "uniform int ui_zero;"
564                                                                    << "uniform int ui_one;"
565                                                                    << ""
566                                                                    << "struct T {"
567                                                                    << "    int             a;"
568                                                                    << "    mediump vec2    b;"
569                                                                    << "};"
570                                                                    << "struct S {"
571                                                                    << "    mediump float   a;"
572                                                                    << "    T               b;"
573                                                                    << "    int             c;"
574                                                                    << "};"
575                                                                    << ""
576                                                                    << "S myFunc (void)"
577                                                                    << "{"
578                                                                    << "    S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);"
579                                                                    << "    s.b = T(ui_zero, ${COORDS}.yz);"
580                                                                    << "    return s;"
581                                                                    << "}"
582                                                                    << ""
583                                                                    << "void main (void)"
584                                                                    << "{"
585                                                                    << "    S s = myFunc();"
586                                                                    << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
587                                                                    << "    ${ASSIGN_POS}"
588                                                                    << "}",
589                                           { c.color.xyz() = c.coords.swizzle(0, 1, 2); });
590
591         LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment",
592                                           LineStream() << "${HEADER}"
593                                                                    << "uniform int ui_zero;"
594                                                                    << "uniform int ui_one;"
595                                                                    << "uniform mediump float uf_one;"
596                                                                    << ""
597                                                                    << "struct S {"
598                                                                    << "    mediump float   a;"
599                                                                    << "    mediump vec3    b;"
600                                                                    << "    int             c;"
601                                                                    << "};"
602                                                                    << ""
603                                                                    << "void main (void)"
604                                                                    << "{"
605                                                                    << "    S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
606                                                                    << "    if (uf_one > 0.0)"
607                                                                    << "        s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
608                                                                    << "    ${DST} = vec4(s.a, s.b.xy, s.c);"
609                                                                    << "    ${ASSIGN_POS}"
610                                                                    << "}",
611                                           { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
612
613         LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop",
614                                           LineStream() << "${HEADER}"
615                                                                    << "uniform int ui_zero;"
616                                                                    << "uniform int ui_one;"
617                                                                    << ""
618                                                                    << "struct S {"
619                                                                    << "    mediump float   a;"
620                                                                    << "    mediump vec3    b;"
621                                                                    << "    int             c;"
622                                                                    << "};"
623                                                                    << ""
624                                                                    << "void main (void)"
625                                                                    << "{"
626                                                                    << "    S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
627                                                                    << "    for (int i = 0; i < 3; i++)"
628                                                                    << "    {"
629                                                                    << "        if (i == 1)"
630                                                                    << "            s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
631                                                                    << "    }"
632                                                                    << "    ${DST} = vec4(s.a, s.b.xy, s.c);"
633                                                                    << "    ${ASSIGN_POS}"
634                                                                    << "}",
635                                           { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
636
637         LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop",
638                                           LineStream() << "${HEADER}"
639                                                                    << "uniform int ui_zero;"
640                                                                    << "uniform int ui_one;"
641                                                                    << "uniform int ui_three;"
642                                                                    << ""
643                                                                    << "struct S {"
644                                                                    << "    mediump float   a;"
645                                                                    << "    mediump vec3    b;"
646                                                                    << "    int             c;"
647                                                                    << "};"
648                                                                    << ""
649                                                                    << "void main (void)"
650                                                                    << "{"
651                                                                    << "    S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);"
652                                                                    << "    for (int i = 0; i < ui_three; i++)"
653                                                                    << "    {"
654                                                                    << "        if (i == ui_one)"
655                                                                    << "            s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);"
656                                                                    << "    }"
657                                                                    << "    ${DST} = vec4(s.a, s.b.xy, s.c);"
658                                                                    << "    ${ASSIGN_POS}"
659                                                                    << "}",
660                                           { c.color.xyz() = c.coords.swizzle(3, 2, 1); });
661
662         LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct",
663                                           LineStream() << "${HEADER}"
664                                                                    << "uniform int ui_zero;"
665                                                                    << "uniform int ui_one;"
666                                                                    << "uniform mediump float uf_one;"
667                                                                    << ""
668                                                                    << "struct T {"
669                                                                    << "    int             a;"
670                                                                    << "    mediump vec2    b;"
671                                                                    << "};"
672                                                                    << "struct S {"
673                                                                    << "    mediump float   a;"
674                                                                    << "    T               b;"
675                                                                    << "    int             c;"
676                                                                    << "};"
677                                                                    << ""
678                                                                    << "void main (void)"
679                                                                    << "{"
680                                                                    << "    S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
681                                                                    << "    if (uf_one > 0.0)"
682                                                                    << "        s.b = T(ui_zero, ${COORDS}.zw);"
683                                                                    << "    ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
684                                                                    << "    ${ASSIGN_POS}"
685                                                                    << "}",
686                                           { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
687
688         LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop",
689                                           LineStream() << "${HEADER}"
690                                                                    << "uniform int ui_zero;"
691                                                                    << "uniform int ui_one;"
692                                                                    << "uniform mediump float uf_one;"
693                                                                    << ""
694                                                                    << "struct T {"
695                                                                    << "    int             a;"
696                                                                    << "    mediump vec2    b;"
697                                                                    << "};"
698                                                                    << "struct S {"
699                                                                    << "    mediump float   a;"
700                                                                    << "    T               b;"
701                                                                    << "    int             c;"
702                                                                    << "};"
703                                                                    << ""
704                                                                    << "void main (void)"
705                                                                    << "{"
706                                                                    << "    S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
707                                                                    << "    for (int i = 0; i < 3; i++)"
708                                                                    << "    {"
709                                                                    << "        if (i == 1)"
710                                                                    << "            s.b = T(ui_zero, ${COORDS}.zw);"
711                                                                    << "    }"
712                                                                    << "    ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
713                                                                    << "    ${ASSIGN_POS}"
714                                                                    << "}",
715                                           { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
716
717         LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop",
718                                           LineStream() << "${HEADER}"
719                                                                    << "uniform int ui_zero;"
720                                                                    << "uniform int ui_one;"
721                                                                    << "uniform int ui_three;"
722                                                                    << "uniform mediump float uf_one;"
723                                                                    << ""
724                                                                    << "struct T {"
725                                                                    << "    int             a;"
726                                                                    << "    mediump vec2    b;"
727                                                                    << "};"
728                                                                    << "struct S {"
729                                                                    << "    mediump float   a;"
730                                                                    << "    T               b;"
731                                                                    << "    int             c;"
732                                                                    << "};"
733                                                                    << ""
734                                                                    << "void main (void)"
735                                                                    << "{"
736                                                                    << "    S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);"
737                                                                    << "    for (int i = 0; i < ui_three; i++)"
738                                                                    << "    {"
739                                                                    << "        if (i == ui_one)"
740                                                                    << "            s.b = T(ui_zero, ${COORDS}.zw);"
741                                                                    << "    }"
742                                                                    << "    ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);"
743                                                                    << "    ${ASSIGN_POS}"
744                                                                    << "}",
745                                           { c.color.xyz() = c.coords.swizzle(0, 2, 3); });
746
747         LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop",
748                                           LineStream() << "${HEADER}"
749                                                                    << "uniform int ui_zero;"
750                                                                    << "uniform int ui_one;"
751                                                                    << "uniform int ui_two;"
752                                                                    << ""
753                                                                    << "struct S {"
754                                                                    << "    mediump float   a;"
755                                                                    << "    mediump int     b;"
756                                                                    << "};"
757                                                                    << ""
758                                                                    << "void main (void)"
759                                                                    << "{"
760                                                                    << "    S s[3];"
761                                                                    << "    s[0] = S(${COORDS}.x, ui_zero);"
762                                                                    << "    s[1].a = ${COORDS}.y;"
763                                                                    << "    s[1].b = -ui_one;"
764                                                                    << "    s[2] = S(${COORDS}.z, ui_two);"
765                                                                    << ""
766                                                                    << "    mediump float rgb[3];"
767                                                                    << "    int alpha = 0;"
768                                                                    << "    for (int i = 0; i < 3; i++)"
769                                                                    << "    {"
770                                                                    << "        rgb[i] = s[2-i].a;"
771                                                                    << "        alpha += s[i].b;"
772                                                                    << "    }"
773                                                                    << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
774                                                                    << "    ${ASSIGN_POS}"
775                                                                    << "}",
776                                           { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
777
778         LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop",
779                                           LineStream() << "${HEADER}"
780                                                                    << "uniform int ui_zero;"
781                                                                    << "uniform int ui_one;"
782                                                                    << "uniform int ui_two;"
783                                                                    << "uniform mediump float uf_two;"
784                                                                    << "uniform mediump float uf_three;"
785                                                                    << "uniform mediump float uf_four;"
786                                                                    << "uniform mediump float uf_half;"
787                                                                    << "uniform mediump float uf_third;"
788                                                                    << "uniform mediump float uf_fourth;"
789                                                                    << "uniform mediump float uf_sixth;"
790                                                                    << ""
791                                                                    << "struct T {"
792                                                                    << "    mediump float   a;"
793                                                                    << "    mediump vec2    b[2];"
794                                                                    << "};"
795                                                                    << "struct S {"
796                                                                    << "    mediump float   a;"
797                                                                    << "    T               b[3];"
798                                                                    << "    int             c;"
799                                                                    << "};"
800                                                                    << ""
801                                                                    << "void main (void)"
802                                                                    << "{"
803                                                                    << "    S s[2];"
804                                                                    << ""
805                                                                    << "    // S[0]"
806                                                                    << "    s[0].a         = ${COORDS}.x;"
807                                                                    << "    s[0].b[0].a    = uf_half;"
808                                                                    << "    s[0].b[0].b[0] = ${COORDS}.yx;"
809                                                                    << "    s[0].b[0].b[1] = ${COORDS}.zx;"
810                                                                    << "    s[0].b[1].a    = uf_third;"
811                                                                    << "    s[0].b[1].b[0] = ${COORDS}.yy;"
812                                                                    << "    s[0].b[1].b[1] = ${COORDS}.wy;"
813                                                                    << "    s[0].b[2].a    = uf_fourth;"
814                                                                    << "    s[0].b[2].b[0] = ${COORDS}.zx;"
815                                                                    << "    s[0].b[2].b[1] = ${COORDS}.zy;"
816                                                                    << "    s[0].c         = ui_zero;"
817                                                                    << ""
818                                                                    << "    // S[1]"
819                                                                    << "    s[1].a         = ${COORDS}.w;"
820                                                                    << "    s[1].b[0].a    = uf_two;"
821                                                                    << "    s[1].b[0].b[0] = ${COORDS}.zx;"
822                                                                    << "    s[1].b[0].b[1] = ${COORDS}.zy;"
823                                                                    << "    s[1].b[1].a    = uf_three;"
824                                                                    << "    s[1].b[1].b[0] = ${COORDS}.zz;"
825                                                                    << "    s[1].b[1].b[1] = ${COORDS}.ww;"
826                                                                    << "    s[1].b[2].a    = uf_four;"
827                                                                    << "    s[1].b[2].b[0] = ${COORDS}.yx;"
828                                                                    << "    s[1].b[2].b[1] = ${COORDS}.wz;"
829                                                                    << "    s[1].c         = ui_one;"
830                                                                    << ""
831                                                                    << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
832                                                                    << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
833                                                                    << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
834                                                                    << "    mediump float a = 1.0;"
835                                                                    << "    for (int i = 0; i < 2; i++)"
836                                                                    << "    {"
837                                                                    << "        for (int j = 0; j < 3; j++)"
838                                                                    << "        {"
839                                                                    << "            r += s[0].b[j].b[i].y;"
840                                                                    << "            g += s[i].b[j].b[0].x;"
841                                                                    << "            b += s[i].b[j].b[1].x;"
842                                                                    << "            a *= s[i].b[j].a;"
843                                                                    << "        }"
844                                                                    << "    }"
845                                                                    << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
846                                                                    << "    ${ASSIGN_POS}"
847                                                                    << "}",
848                                           { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
849
850         LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop",
851                                           LineStream() << "${HEADER}"
852                                                                    << "uniform int ui_zero;"
853                                                                    << "uniform int ui_one;"
854                                                                    << "uniform int ui_two;"
855                                                                    << "uniform int ui_three;"
856                                                                    << ""
857                                                                    << "struct S {"
858                                                                    << "    mediump float   a;"
859                                                                    << "    mediump int     b;"
860                                                                    << "};"
861                                                                    << ""
862                                                                    << "void main (void)"
863                                                                    << "{"
864                                                                    << "    S s[3];"
865                                                                    << "    s[0] = S(${COORDS}.x, ui_zero);"
866                                                                    << "    s[1].a = ${COORDS}.y;"
867                                                                    << "    s[1].b = -ui_one;"
868                                                                    << "    s[2] = S(${COORDS}.z, ui_two);"
869                                                                    << ""
870                                                                    << "    mediump float rgb[3];"
871                                                                    << "    int alpha = 0;"
872                                                                    << "    for (int i = 0; i < ui_three; i++)"
873                                                                    << "    {"
874                                                                    << "        rgb[i] = s[2-i].a;"
875                                                                    << "        alpha += s[i].b;"
876                                                                    << "    }"
877                                                                    << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
878                                                                    << "    ${ASSIGN_POS}"
879                                                                    << "}",
880                                           { c.color.xyz() = c.coords.swizzle(2, 1, 0); });
881
882         LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop",
883                                           LineStream() << "${HEADER}"
884                                                                    << "uniform int ui_zero;"
885                                                                    << "uniform int ui_one;"
886                                                                    << "uniform int ui_two;"
887                                                                    << "uniform int ui_three;"
888                                                                    << "uniform mediump float uf_two;"
889                                                                    << "uniform mediump float uf_three;"
890                                                                    << "uniform mediump float uf_four;"
891                                                                    << "uniform mediump float uf_half;"
892                                                                    << "uniform mediump float uf_third;"
893                                                                    << "uniform mediump float uf_fourth;"
894                                                                    << "uniform mediump float uf_sixth;"
895                                                                    << ""
896                                                                    << "struct T {"
897                                                                    << "    mediump float   a;"
898                                                                    << "    mediump vec2    b[2];"
899                                                                    << "};"
900                                                                    << "struct S {"
901                                                                    << "    mediump float   a;"
902                                                                    << "    T               b[3];"
903                                                                    << "    int             c;"
904                                                                    << "};"
905                                                                    << ""
906                                                                    << "void main (void)"
907                                                                    << "{"
908                                                                    << "    S s[2];"
909                                                                    << ""
910                                                                    << "    // S[0]"
911                                                                    << "    s[0].a         = ${COORDS}.x;"
912                                                                    << "    s[0].b[0].a    = uf_half;"
913                                                                    << "    s[0].b[0].b[0] = ${COORDS}.yx;"
914                                                                    << "    s[0].b[0].b[1] = ${COORDS}.zx;"
915                                                                    << "    s[0].b[1].a    = uf_third;"
916                                                                    << "    s[0].b[1].b[0] = ${COORDS}.yy;"
917                                                                    << "    s[0].b[1].b[1] = ${COORDS}.wy;"
918                                                                    << "    s[0].b[2].a    = uf_fourth;"
919                                                                    << "    s[0].b[2].b[0] = ${COORDS}.zx;"
920                                                                    << "    s[0].b[2].b[1] = ${COORDS}.zy;"
921                                                                    << "    s[0].c         = ui_zero;"
922                                                                    << ""
923                                                                    << "    // S[1]"
924                                                                    << "    s[1].a         = ${COORDS}.w;"
925                                                                    << "    s[1].b[0].a    = uf_two;"
926                                                                    << "    s[1].b[0].b[0] = ${COORDS}.zx;"
927                                                                    << "    s[1].b[0].b[1] = ${COORDS}.zy;"
928                                                                    << "    s[1].b[1].a    = uf_three;"
929                                                                    << "    s[1].b[1].b[0] = ${COORDS}.zz;"
930                                                                    << "    s[1].b[1].b[1] = ${COORDS}.ww;"
931                                                                    << "    s[1].b[2].a    = uf_four;"
932                                                                    << "    s[1].b[2].b[0] = ${COORDS}.yx;"
933                                                                    << "    s[1].b[2].b[1] = ${COORDS}.wz;"
934                                                                    << "    s[1].c         = ui_one;"
935                                                                    << ""
936                                                                    << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
937                                                                    << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
938                                                                    << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
939                                                                    << "    mediump float a = 1.0;"
940                                                                    << "    for (int i = 0; i < ui_two; i++)"
941                                                                    << "    {"
942                                                                    << "        for (int j = 0; j < ui_three; j++)"
943                                                                    << "        {"
944                                                                    << "            r += s[0].b[j].b[i].y;"
945                                                                    << "            g += s[i].b[j].b[0].x;"
946                                                                    << "            b += s[i].b[j].b[1].x;"
947                                                                    << "            a *= s[i].b[j].a;"
948                                                                    << "        }"
949                                                                    << "    }"
950                                                                    << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
951                                                                    << "    ${ASSIGN_POS}"
952                                                                    << "}",
953                                           { c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; });
954 }
955
956 class UniformStructTests : public TestCaseGroup
957 {
958 public:
959         UniformStructTests(Context& context, glu::GLSLVersion glslVersion)
960                 : TestCaseGroup(context, "uniform", "Uniform structs"), m_glslVersion(glslVersion)
961         {
962         }
963
964         ~UniformStructTests(void)
965         {
966         }
967
968         virtual void init(void);
969
970 private:
971         glu::GLSLVersion m_glslVersion;
972 };
973
974 namespace
975 {
976
977 #define CHECK_SET_UNIFORM(NAME) GLU_EXPECT_NO_ERROR(gl.getError(), (string("Failed to set ") + NAME).c_str())
978
979 #define MAKE_SET_VEC_UNIFORM(VECTYPE, SETUNIFORM)                                                            \
980         void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE& vec) \
981         {                                                                                                        \
982                 int loc = gl.getUniformLocation(programID, name);                                                    \
983                 SETUNIFORM(loc, 1, vec.getPtr());                                                                    \
984                 CHECK_SET_UNIFORM(name);                                                                             \
985         }                                                                                                        \
986         struct SetUniform##VECTYPE##Dummy_s                                                                      \
987         {                                                                                                        \
988                 int unused;                                                                                          \
989         }
990
991 #define MAKE_SET_VEC_UNIFORM_PTR(VECTYPE, SETUNIFORM)                                                        \
992         void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const tcu::VECTYPE* vec, \
993                                         int arraySize)                                                                           \
994         {                                                                                                        \
995                 int loc = gl.getUniformLocation(programID, name);                                                    \
996                 SETUNIFORM(loc, arraySize, vec->getPtr());                                                           \
997                 CHECK_SET_UNIFORM(name);                                                                             \
998         }                                                                                                        \
999         struct SetUniformPtr##VECTYPE##Dummy_s                                                                   \
1000         {                                                                                                        \
1001                 int unused;                                                                                          \
1002         }
1003
1004 MAKE_SET_VEC_UNIFORM(Vec2, gl.uniform2fv);
1005 MAKE_SET_VEC_UNIFORM(Vec3, gl.uniform3fv);
1006 MAKE_SET_VEC_UNIFORM_PTR(Vec2, gl.uniform2fv);
1007
1008 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, float value)
1009 {
1010         int loc = gl.getUniformLocation(programID, name);
1011         gl.uniform1f(loc, value);
1012         CHECK_SET_UNIFORM(name);
1013 }
1014
1015 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, int value)
1016 {
1017         int loc = gl.getUniformLocation(programID, name);
1018         gl.uniform1i(loc, value);
1019         CHECK_SET_UNIFORM(name);
1020 }
1021
1022 void setUniform(const glw::Functions& gl, deUint32 programID, const char* name, const float* value, int arraySize)
1023 {
1024         int loc = gl.getUniformLocation(programID, name);
1025         gl.uniform1fv(loc, arraySize, value);
1026         CHECK_SET_UNIFORM(name);
1027 }
1028
1029 } // anonymous
1030
1031 void UniformStructTests::init(void)
1032 {
1033 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, TEXTURES, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY)      \
1034         do                                                                                                       \
1035         {                                                                                                        \
1036                 struct SetUniforms_##NAME                                                                            \
1037                 {                                                                                                    \
1038                         static void setUniforms(const glw::Functions& gl, deUint32 programID,                            \
1039                                                                         const tcu::Vec4& constCoords) SET_UNIFORMS_BODY                          \
1040                 };                                                                                                   \
1041                 struct Eval_##NAME                                                                                   \
1042                 {                                                                                                    \
1043                         static void eval(ShaderEvalContext& c) EVAL_FUNC_BODY                                            \
1044                 };                                                                                                   \
1045                 addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, m_glslVersion, true, TEXTURES,    \
1046                                                                   Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC));          \
1047                 addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, m_glslVersion, false, TEXTURES, \
1048                                                                   Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC));          \
1049         } while (deGetFalse())
1050
1051         UNIFORM_STRUCT_CASE(basic, "Basic struct usage", false,
1052                                                 LineStream() << "${HEADER}"
1053                                                                          << "uniform int ui_one;"
1054                                                                          << ""
1055                                                                          << "struct S {"
1056                                                                          << "    mediump float   a;"
1057                                                                          << "    mediump vec3    b;"
1058                                                                          << "    int             c;"
1059                                                                          << "};"
1060                                                                          << "uniform S s;"
1061                                                                          << ""
1062                                                                          << "void main (void)"
1063                                                                          << "{"
1064                                                                          << "    ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);"
1065                                                                          << "    ${ASSIGN_POS}"
1066                                                                          << "}",
1067                                                 {
1068                                                         setUniform(gl, programID, "s.a", constCoords.x());
1069                                                         setUniform(gl, programID, "s.b", constCoords.swizzle(1, 2, 3));
1070                                                         setUniform(gl, programID, "s.c", 1);
1071                                                 },
1072                                                 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1073
1074         UNIFORM_STRUCT_CASE(nested, "Nested struct", false,
1075                                                 LineStream() << "${HEADER}"
1076                                                                          << "uniform int ui_zero;"
1077                                                                          << "uniform int ui_one;"
1078                                                                          << ""
1079                                                                          << "struct T {"
1080                                                                          << "    int             a;"
1081                                                                          << "    mediump vec2    b;"
1082                                                                          << "};"
1083                                                                          << "struct S {"
1084                                                                          << "    mediump float   a;"
1085                                                                          << "    T               b;"
1086                                                                          << "    int             c;"
1087                                                                          << "};"
1088                                                                          << "uniform S s;"
1089                                                                          << ""
1090                                                                          << "void main (void)"
1091                                                                          << "{"
1092                                                                          << "    ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);"
1093                                                                          << "    ${ASSIGN_POS}"
1094                                                                          << "}",
1095                                                 {
1096                                                         setUniform(gl, programID, "s.a", constCoords.x());
1097                                                         setUniform(gl, programID, "s.b.a", 0);
1098                                                         setUniform(gl, programID, "s.b.b", constCoords.swizzle(1, 2));
1099                                                         setUniform(gl, programID, "s.c", 1);
1100                                                 },
1101                                                 { c.color.xyz() = c.constCoords.swizzle(0, 1, 2); });
1102
1103         UNIFORM_STRUCT_CASE(array_member, "Struct with array member", false,
1104                                                 LineStream() << "${HEADER}"
1105                                                                          << "uniform int ui_one;"
1106                                                                          << ""
1107                                                                          << "struct S {"
1108                                                                          << "    mediump float   a;"
1109                                                                          << "    mediump float   b[3];"
1110                                                                          << "    int             c;"
1111                                                                          << "};"
1112                                                                          << "uniform S s;"
1113                                                                          << ""
1114                                                                          << "void main (void)"
1115                                                                          << "{"
1116                                                                          << "    ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);"
1117                                                                          << "    ${ASSIGN_POS}"
1118                                                                          << "}",
1119                                                 {
1120                                                         setUniform(gl, programID, "s.a", constCoords.w());
1121                                                         setUniform(gl, programID, "s.c", 1);
1122
1123                                                         float b[3];
1124                                                         b[0] = constCoords.z();
1125                                                         b[1] = constCoords.y();
1126                                                         b[2] = constCoords.x();
1127                                                         setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1128                                                 },
1129                                                 { c.color.xyz() = c.constCoords.swizzle(3, 2, 1); });
1130
1131         UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", false,
1132                                                 LineStream() << "${HEADER}"
1133                                                                          << "uniform int ui_zero;"
1134                                                                          << "uniform int ui_one;"
1135                                                                          << "uniform int ui_two;"
1136                                                                          << ""
1137                                                                          << "struct S {"
1138                                                                          << "    mediump float   a;"
1139                                                                          << "    mediump float   b[3];"
1140                                                                          << "    int             c;"
1141                                                                          << "};"
1142                                                                          << "uniform S s;"
1143                                                                          << ""
1144                                                                          << "void main (void)"
1145                                                                          << "{"
1146                                                                          << "    ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);"
1147                                                                          << "    ${ASSIGN_POS}"
1148                                                                          << "}",
1149                                                 {
1150                                                         setUniform(gl, programID, "s.a", constCoords.w());
1151                                                         setUniform(gl, programID, "s.c", 1);
1152
1153                                                         float b[3];
1154                                                         b[0] = constCoords.z();
1155                                                         b[1] = constCoords.y();
1156                                                         b[2] = constCoords.x();
1157                                                         setUniform(gl, programID, "s.b", b, DE_LENGTH_OF_ARRAY(b));
1158                                                 },
1159                                                 { c.color.xyz() = c.constCoords.swizzle(1, 2, 0); });
1160
1161         UNIFORM_STRUCT_CASE(struct_array, "Struct array", false,
1162                                                 LineStream() << "${HEADER}"
1163                                                                          << "uniform int ui_zero;"
1164                                                                          << "uniform int ui_one;"
1165                                                                          << "uniform int ui_two;"
1166                                                                          << ""
1167                                                                          << "struct S {"
1168                                                                          << "    mediump float   a;"
1169                                                                          << "    mediump int     b;"
1170                                                                          << "};"
1171                                                                          << "uniform S s[3];"
1172                                                                          << ""
1173                                                                          << "void main (void)"
1174                                                                          << "{"
1175                                                                          << "    ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);"
1176                                                                          << "    ${ASSIGN_POS}"
1177                                                                          << "}",
1178                                                 {
1179                                                         setUniform(gl, programID, "s[0].a", constCoords.x());
1180                                                         setUniform(gl, programID, "s[0].b", 0);
1181                                                         setUniform(gl, programID, "s[1].a", constCoords.y());
1182                                                         setUniform(gl, programID, "s[1].b", 1);
1183                                                         setUniform(gl, programID, "s[2].a", constCoords.z());
1184                                                         setUniform(gl, programID, "s[2].b", 2);
1185                                                 },
1186                                                 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1187
1188         UNIFORM_STRUCT_CASE(
1189                 struct_array_dynamic_index, "Struct array with dynamic indexing", false,
1190                 LineStream()
1191                         << "${HEADER}"
1192                         << "uniform int ui_zero;"
1193                         << "uniform int ui_one;"
1194                         << "uniform int ui_two;"
1195                         << ""
1196                         << "struct S {"
1197                         << "    mediump float   a;"
1198                         << "    mediump int     b;"
1199                         << "};"
1200                         << "uniform S s[3];"
1201                         << ""
1202                         << "void main (void)"
1203                         << "{"
1204                         << "    ${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);"
1205                         << "    ${ASSIGN_POS}"
1206                         << "}",
1207                 {
1208                         setUniform(gl, programID, "s[0].a", constCoords.x());
1209                         setUniform(gl, programID, "s[0].b", 0);
1210                         setUniform(gl, programID, "s[1].a", constCoords.y());
1211                         setUniform(gl, programID, "s[1].b", 1);
1212                         setUniform(gl, programID, "s[2].a", constCoords.z());
1213                         setUniform(gl, programID, "s[2].b", 2);
1214                 },
1215                 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1216
1217         UNIFORM_STRUCT_CASE(
1218                 nested_struct_array, "Nested struct array", false,
1219                 LineStream() << "${HEADER}"
1220                                          << "struct T {"
1221                                          << "    mediump float   a;"
1222                                          << "    mediump vec2    b[2];"
1223                                          << "};"
1224                                          << "struct S {"
1225                                          << "    mediump float   a;"
1226                                          << "    T               b[3];"
1227                                          << "    int             c;"
1228                                          << "};"
1229                                          << "uniform S s[2];"
1230                                          << ""
1231                                          << "void main (void)"
1232                                          << "{"
1233                                          << "    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"
1234                                          << "    mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4"
1235                                          << "    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 "
1236                                                 "+ w) * 0.333"
1237                                          << "    mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0"
1238                                          << "    ${DST} = vec4(r, g, b, a);"
1239                                          << "    ${ASSIGN_POS}"
1240                                          << "}",
1241                 {
1242                         tcu::Vec2 arr[2];
1243
1244                         setUniform(gl, programID, "s[0].a", constCoords.x());
1245                         arr[0] = constCoords.swizzle(0, 1);
1246                         arr[1] = constCoords.swizzle(2, 3);
1247                         setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1248                         setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1249                         arr[0] = constCoords.swizzle(2, 3);
1250                         arr[1] = constCoords.swizzle(0, 1);
1251                         setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1252                         setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1253                         arr[0] = constCoords.swizzle(0, 2);
1254                         arr[1] = constCoords.swizzle(1, 3);
1255                         setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1256                         setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1257                         setUniform(gl, programID, "s[0].c", 0);
1258
1259                         setUniform(gl, programID, "s[1].a", constCoords.w());
1260                         arr[0] = constCoords.swizzle(0, 0);
1261                         arr[1] = constCoords.swizzle(1, 1);
1262                         setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1263                         setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1264                         arr[0] = constCoords.swizzle(2, 2);
1265                         arr[1] = constCoords.swizzle(3, 3);
1266                         setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1267                         setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1268                         arr[0] = constCoords.swizzle(1, 0);
1269                         arr[1] = constCoords.swizzle(3, 2);
1270                         setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1271                         setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1272                         setUniform(gl, programID, "s[1].c", 1);
1273                 },
1274                 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
1275
1276         UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", false,
1277                                                 LineStream() << "${HEADER}"
1278                                                                          << "uniform int ui_zero;"
1279                                                                          << "uniform int ui_one;"
1280                                                                          << "uniform int ui_two;"
1281                                                                          << ""
1282                                                                          << "struct T {"
1283                                                                          << "    mediump float   a;"
1284                                                                          << "    mediump vec2    b[2];"
1285                                                                          << "};"
1286                                                                          << "struct S {"
1287                                                                          << "    mediump float   a;"
1288                                                                          << "    T               b[3];"
1289                                                                          << "    int             c;"
1290                                                                          << "};"
1291                                                                          << "uniform S s[2];"
1292                                                                          << ""
1293                                                                          << "void main (void)"
1294                                                                          << "{"
1295                                                                          << "    mediump float r = (s[0].b[ui_one].b[ui_one-1].x + "
1296                                                                                 "s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5"
1297                                                                          << "    mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a "
1298                                                                                 "* s[ui_one].b[2].a; // x * 0.25 * 4"
1299                                                                          << "    mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + "
1300                                                                                 "s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w "
1301                                                                                 "+ w + w) * 0.333"
1302                                                                          << "    mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - "
1303                                                                                 "s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0"
1304                                                                          << "    ${DST} = vec4(r, g, b, a);"
1305                                                                          << "    ${ASSIGN_POS}"
1306                                                                          << "}",
1307                                                 {
1308                                                         tcu::Vec2 arr[2];
1309
1310                                                         setUniform(gl, programID, "s[0].a", constCoords.x());
1311                                                         arr[0] = constCoords.swizzle(0, 1);
1312                                                         arr[1] = constCoords.swizzle(2, 3);
1313                                                         setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1314                                                         setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1315                                                         arr[0] = constCoords.swizzle(2, 3);
1316                                                         arr[1] = constCoords.swizzle(0, 1);
1317                                                         setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1318                                                         setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1319                                                         arr[0] = constCoords.swizzle(0, 2);
1320                                                         arr[1] = constCoords.swizzle(1, 3);
1321                                                         setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1322                                                         setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1323                                                         setUniform(gl, programID, "s[0].c", 0);
1324
1325                                                         setUniform(gl, programID, "s[1].a", constCoords.w());
1326                                                         arr[0] = constCoords.swizzle(0, 0);
1327                                                         arr[1] = constCoords.swizzle(1, 1);
1328                                                         setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1329                                                         setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1330                                                         arr[0] = constCoords.swizzle(2, 2);
1331                                                         arr[1] = constCoords.swizzle(3, 3);
1332                                                         setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1333                                                         setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1334                                                         arr[0] = constCoords.swizzle(1, 0);
1335                                                         arr[1] = constCoords.swizzle(3, 2);
1336                                                         setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1337                                                         setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1338                                                         setUniform(gl, programID, "s[1].c", 1);
1339                                                 },
1340                                                 { c.color.xyz() = c.constCoords.swizzle(2, 0, 3); });
1341
1342         UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", false,
1343                                                 LineStream() << "${HEADER}"
1344                                                                          << "uniform int ui_zero;"
1345                                                                          << "uniform int ui_one;"
1346                                                                          << "uniform int ui_two;"
1347                                                                          << ""
1348                                                                          << "struct S {"
1349                                                                          << "    mediump float   a;"
1350                                                                          << "    mediump int     b;"
1351                                                                          << "};"
1352                                                                          << "uniform S s[3];"
1353                                                                          << ""
1354                                                                          << "void main (void)"
1355                                                                          << "{"
1356                                                                          << "    mediump float rgb[3];"
1357                                                                          << "    int alpha = 0;"
1358                                                                          << "    for (int i = 0; i < 3; i++)"
1359                                                                          << "    {"
1360                                                                          << "        rgb[i] = s[2-i].a;"
1361                                                                          << "        alpha += s[i].b;"
1362                                                                          << "    }"
1363                                                                          << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1364                                                                          << "    ${ASSIGN_POS}"
1365                                                                          << "}",
1366                                                 {
1367                                                         setUniform(gl, programID, "s[0].a", constCoords.x());
1368                                                         setUniform(gl, programID, "s[0].b", 0);
1369                                                         setUniform(gl, programID, "s[1].a", constCoords.y());
1370                                                         setUniform(gl, programID, "s[1].b", -1);
1371                                                         setUniform(gl, programID, "s[2].a", constCoords.z());
1372                                                         setUniform(gl, programID, "s[2].b", 2);
1373                                                 },
1374                                                 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1375
1376         UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", false,
1377                                                 LineStream() << "${HEADER}"
1378                                                                          << "uniform int ui_zero;"
1379                                                                          << "uniform int ui_one;"
1380                                                                          << "uniform int ui_two;"
1381                                                                          << "uniform mediump float uf_two;"
1382                                                                          << "uniform mediump float uf_three;"
1383                                                                          << "uniform mediump float uf_four;"
1384                                                                          << "uniform mediump float uf_half;"
1385                                                                          << "uniform mediump float uf_third;"
1386                                                                          << "uniform mediump float uf_fourth;"
1387                                                                          << "uniform mediump float uf_sixth;"
1388                                                                          << ""
1389                                                                          << "struct T {"
1390                                                                          << "    mediump float   a;"
1391                                                                          << "    mediump vec2    b[2];"
1392                                                                          << "};"
1393                                                                          << "struct S {"
1394                                                                          << "    mediump float   a;"
1395                                                                          << "    T               b[3];"
1396                                                                          << "    int             c;"
1397                                                                          << "};"
1398                                                                          << "uniform S s[2];"
1399                                                                          << ""
1400                                                                          << "void main (void)"
1401                                                                          << "{"
1402                                                                          << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1403                                                                          << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1404                                                                          << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1405                                                                          << "    mediump float a = 1.0;"
1406                                                                          << "    for (int i = 0; i < 2; i++)"
1407                                                                          << "    {"
1408                                                                          << "        for (int j = 0; j < 3; j++)"
1409                                                                          << "        {"
1410                                                                          << "            r += s[0].b[j].b[i].y;"
1411                                                                          << "            g += s[i].b[j].b[0].x;"
1412                                                                          << "            b += s[i].b[j].b[1].x;"
1413                                                                          << "            a *= s[i].b[j].a;"
1414                                                                          << "        }"
1415                                                                          << "    }"
1416                                                                          << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1417                                                                          << "    ${ASSIGN_POS}"
1418                                                                          << "}",
1419                                                 {
1420                                                         tcu::Vec2 arr[2];
1421
1422                                                         setUniform(gl, programID, "s[0].a", constCoords.x());
1423                                                         arr[0] = constCoords.swizzle(1, 0);
1424                                                         arr[1] = constCoords.swizzle(2, 0);
1425                                                         setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1426                                                         setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1427                                                         arr[0] = constCoords.swizzle(1, 1);
1428                                                         arr[1] = constCoords.swizzle(3, 1);
1429                                                         setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1430                                                         setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1431                                                         arr[0] = constCoords.swizzle(2, 1);
1432                                                         arr[1] = constCoords.swizzle(2, 1);
1433                                                         setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1434                                                         setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1435                                                         setUniform(gl, programID, "s[0].c", 0);
1436
1437                                                         setUniform(gl, programID, "s[1].a", constCoords.w());
1438                                                         arr[0] = constCoords.swizzle(2, 0);
1439                                                         arr[1] = constCoords.swizzle(2, 1);
1440                                                         setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1441                                                         setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1442                                                         arr[0] = constCoords.swizzle(2, 2);
1443                                                         arr[1] = constCoords.swizzle(3, 3);
1444                                                         setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1445                                                         setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1446                                                         arr[0] = constCoords.swizzle(1, 0);
1447                                                         arr[1] = constCoords.swizzle(3, 2);
1448                                                         setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1449                                                         setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1450                                                         setUniform(gl, programID, "s[1].c", 1);
1451                                                 },
1452                                                 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1453
1454         UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", false,
1455                                                 LineStream() << "${HEADER}"
1456                                                                          << "uniform int ui_zero;"
1457                                                                          << "uniform int ui_one;"
1458                                                                          << "uniform int ui_two;"
1459                                                                          << "uniform int ui_three;"
1460                                                                          << ""
1461                                                                          << "struct S {"
1462                                                                          << "    mediump float   a;"
1463                                                                          << "    mediump int     b;"
1464                                                                          << "};"
1465                                                                          << "uniform S s[3];"
1466                                                                          << ""
1467                                                                          << "void main (void)"
1468                                                                          << "{"
1469                                                                          << "    mediump float rgb[3];"
1470                                                                          << "    int alpha = 0;"
1471                                                                          << "    for (int i = 0; i < ui_three; i++)"
1472                                                                          << "    {"
1473                                                                          << "        rgb[i] = s[2-i].a;"
1474                                                                          << "        alpha += s[i].b;"
1475                                                                          << "    }"
1476                                                                          << "    ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);"
1477                                                                          << "    ${ASSIGN_POS}"
1478                                                                          << "}",
1479                                                 {
1480                                                         setUniform(gl, programID, "s[0].a", constCoords.x());
1481                                                         setUniform(gl, programID, "s[0].b", 0);
1482                                                         setUniform(gl, programID, "s[1].a", constCoords.y());
1483                                                         setUniform(gl, programID, "s[1].b", -1);
1484                                                         setUniform(gl, programID, "s[2].a", constCoords.z());
1485                                                         setUniform(gl, programID, "s[2].b", 2);
1486                                                 },
1487                                                 { c.color.xyz() = c.constCoords.swizzle(2, 1, 0); });
1488
1489         UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", false,
1490                                                 LineStream() << "${HEADER}"
1491                                                                          << "uniform int ui_zero;"
1492                                                                          << "uniform int ui_one;"
1493                                                                          << "uniform int ui_two;"
1494                                                                          << "uniform int ui_three;"
1495                                                                          << "uniform mediump float uf_two;"
1496                                                                          << "uniform mediump float uf_three;"
1497                                                                          << "uniform mediump float uf_four;"
1498                                                                          << "uniform mediump float uf_half;"
1499                                                                          << "uniform mediump float uf_third;"
1500                                                                          << "uniform mediump float uf_fourth;"
1501                                                                          << "uniform mediump float uf_sixth;"
1502                                                                          << ""
1503                                                                          << "struct T {"
1504                                                                          << "    mediump float   a;"
1505                                                                          << "    mediump vec2    b[2];"
1506                                                                          << "};"
1507                                                                          << "struct S {"
1508                                                                          << "    mediump float   a;"
1509                                                                          << "    T               b[3];"
1510                                                                          << "    int             c;"
1511                                                                          << "};"
1512                                                                          << "uniform S s[2];"
1513                                                                          << ""
1514                                                                          << "void main (void)"
1515                                                                          << "{"
1516                                                                          << "    mediump float r = 0.0; // (x*3 + y*3) / 6.0"
1517                                                                          << "    mediump float g = 0.0; // (y*3 + z*3) / 6.0"
1518                                                                          << "    mediump float b = 0.0; // (z*3 + w*3) / 6.0"
1519                                                                          << "    mediump float a = 1.0;"
1520                                                                          << "    for (int i = 0; i < ui_two; i++)"
1521                                                                          << "    {"
1522                                                                          << "        for (int j = 0; j < ui_three; j++)"
1523                                                                          << "        {"
1524                                                                          << "            r += s[0].b[j].b[i].y;"
1525                                                                          << "            g += s[i].b[j].b[0].x;"
1526                                                                          << "            b += s[i].b[j].b[1].x;"
1527                                                                          << "            a *= s[i].b[j].a;"
1528                                                                          << "        }"
1529                                                                          << "    }"
1530                                                                          << "    ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);"
1531                                                                          << "    ${ASSIGN_POS}"
1532                                                                          << "}",
1533                                                 {
1534                                                         tcu::Vec2 arr[2];
1535
1536                                                         setUniform(gl, programID, "s[0].a", constCoords.x());
1537                                                         arr[0] = constCoords.swizzle(1, 0);
1538                                                         arr[1] = constCoords.swizzle(2, 0);
1539                                                         setUniform(gl, programID, "s[0].b[0].a", 0.5f);
1540                                                         setUniform(gl, programID, "s[0].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1541                                                         arr[0] = constCoords.swizzle(1, 1);
1542                                                         arr[1] = constCoords.swizzle(3, 1);
1543                                                         setUniform(gl, programID, "s[0].b[1].a", 1.0f / 3.0f);
1544                                                         setUniform(gl, programID, "s[0].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1545                                                         arr[0] = constCoords.swizzle(2, 1);
1546                                                         arr[1] = constCoords.swizzle(2, 1);
1547                                                         setUniform(gl, programID, "s[0].b[2].a", 1.0f / 4.0f);
1548                                                         setUniform(gl, programID, "s[0].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1549                                                         setUniform(gl, programID, "s[0].c", 0);
1550
1551                                                         setUniform(gl, programID, "s[1].a", constCoords.w());
1552                                                         arr[0] = constCoords.swizzle(2, 0);
1553                                                         arr[1] = constCoords.swizzle(2, 1);
1554                                                         setUniform(gl, programID, "s[1].b[0].a", 2.0f);
1555                                                         setUniform(gl, programID, "s[1].b[0].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1556                                                         arr[0] = constCoords.swizzle(2, 2);
1557                                                         arr[1] = constCoords.swizzle(3, 3);
1558                                                         setUniform(gl, programID, "s[1].b[1].a", 3.0f);
1559                                                         setUniform(gl, programID, "s[1].b[1].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1560                                                         arr[0] = constCoords.swizzle(1, 0);
1561                                                         arr[1] = constCoords.swizzle(3, 2);
1562                                                         setUniform(gl, programID, "s[1].b[2].a", 4.0f);
1563                                                         setUniform(gl, programID, "s[1].b[2].b", &arr[0], DE_LENGTH_OF_ARRAY(arr));
1564                                                         setUniform(gl, programID, "s[1].c", 1);
1565                                                 },
1566                                                 { c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; });
1567
1568         UNIFORM_STRUCT_CASE(
1569                 sampler, "Sampler in struct", true,
1570                 LineStream() << "${HEADER}"
1571                                          << "uniform int ui_one;"
1572                                          << ""
1573                                          << "struct S {"
1574                                          << "    mediump float   a;"
1575                                          << "    mediump vec3    b;"
1576                                          << "    sampler2D       c;"
1577                                          << "};"
1578                                          << "uniform S s;"
1579                                          << ""
1580                                          << "void main (void)"
1581                                          << "{"
1582                                          << "    ${DST} = vec4(texture(s.c, ${COORDS}.xy * s.b.xy + s.b.z).rgb, s.a);"
1583                                          << "    ${ASSIGN_POS}"
1584                                          << "}",
1585                 {
1586                         DE_UNREF(constCoords);
1587                         setUniform(gl, programID, "s.a", 1.0f);
1588                         setUniform(gl, programID, "s.b", tcu::Vec3(0.75f, 0.75f, 0.1f));
1589                         setUniform(gl, programID, "s.c", TEXTURE_GRADIENT);
1590                 },
1591                 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1592
1593         UNIFORM_STRUCT_CASE(
1594                 sampler_nested, "Sampler in nested struct", true,
1595                 LineStream() << "${HEADER}"
1596                                          << "uniform int ui_zero;"
1597                                          << "uniform int ui_one;"
1598                                          << ""
1599                                          << "struct T {"
1600                                          << "    sampler2D       a;"
1601                                          << "    mediump vec2    b;"
1602                                          << "};"
1603                                          << "struct S {"
1604                                          << "    mediump float   a;"
1605                                          << "    T               b;"
1606                                          << "    int             c;"
1607                                          << "};"
1608                                          << "uniform S s;"
1609                                          << ""
1610                                          << "void main (void)"
1611                                          << "{"
1612                                          << "    ${DST} = vec4(texture(s.b.a, ${COORDS}.xy * s.b.b + s.a).rgb, s.c);"
1613                                          << "    ${ASSIGN_POS}"
1614                                          << "}",
1615                 {
1616                         DE_UNREF(constCoords);
1617                         setUniform(gl, programID, "s.a", 0.1f);
1618                         setUniform(gl, programID, "s.b.a", TEXTURE_GRADIENT);
1619                         setUniform(gl, programID, "s.b.b", tcu::Vec2(0.75f, 0.75f));
1620                         setUniform(gl, programID, "s.c", 1);
1621                 },
1622                 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1623
1624         UNIFORM_STRUCT_CASE(
1625                 sampler_array, "Sampler in struct array", true,
1626                 LineStream() << "${HEADER}"
1627                                          << "uniform int ui_one;"
1628                                          << ""
1629                                          << "struct S {"
1630                                          << "    mediump float   a;"
1631                                          << "    mediump vec3    b;"
1632                                          << "    sampler2D       c;"
1633                                          << "};"
1634                                          << "uniform S s[2];"
1635                                          << ""
1636                                          << "void main (void)"
1637                                          << "{"
1638                                          << "    ${DST} = vec4(texture(s[1].c, ${COORDS}.xy * s[0].b.xy + s[1].b.z).rgb, s[0].a);"
1639                                          << "    ${ASSIGN_POS}"
1640                                          << "}",
1641                 {
1642                         DE_UNREF(constCoords);
1643                         setUniform(gl, programID, "s[0].a", 1.0f);
1644                         setUniform(gl, programID, "s[0].b", tcu::Vec3(0.75f, 0.75f, 0.25f));
1645                         setUniform(gl, programID, "s[0].c", 1);
1646                         setUniform(gl, programID, "s[1].a", 0.0f);
1647                         setUniform(gl, programID, "s[1].b", tcu::Vec3(0.5f, 0.5f, 0.1f));
1648                         setUniform(gl, programID, "s[1].c", TEXTURE_GRADIENT);
1649                 },
1650                 { c.color.xyz() = c.texture2D(TEXTURE_GRADIENT, c.coords.swizzle(0, 1) * 0.75f + 0.1f).swizzle(0, 1, 2); });
1651 }
1652
1653 ShaderStructTests::ShaderStructTests(Context& context, glu::GLSLVersion glslVersion)
1654         : TestCaseGroup(context, "struct", "Struct Tests"), m_glslVersion(glslVersion)
1655 {
1656 }
1657
1658 ShaderStructTests::~ShaderStructTests(void)
1659 {
1660 }
1661
1662 void ShaderStructTests::init(void)
1663 {
1664         addChild(new LocalStructTests(m_context, m_glslVersion));
1665         addChild(new UniformStructTests(m_context, m_glslVersion));
1666 }
1667
1668 } // deqp