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