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