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