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