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