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