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