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